summary refs log tree commit diff stats
path: root/hw
diff options
context:
space:
mode:
Diffstat (limited to 'hw')
-rw-r--r--hw/9pfs/codir.c13
-rw-r--r--hw/9pfs/cofile.c19
-rw-r--r--hw/9pfs/virtio-9p-coth.h4
-rw-r--r--hw/9pfs/virtio-9p-device.c2
-rw-r--r--hw/9pfs/virtio-9p.c486
-rw-r--r--hw/9pfs/virtio-9p.h24
-rw-r--r--hw/an5206.c12
-rw-r--r--hw/arm-misc.h5
-rw-r--r--hw/armv7m.c22
-rw-r--r--hw/axis_dev88.c16
-rw-r--r--hw/cirrus_vga.c2
-rw-r--r--hw/collie.c7
-rw-r--r--hw/dec_pci.c13
-rw-r--r--hw/dummy_m68k.c7
-rw-r--r--hw/fdc.c46
-rw-r--r--hw/flash.h13
-rw-r--r--hw/grackle_pci.c13
-rw-r--r--hw/gumstix.c6
-rw-r--r--hw/ide/core.c35
-rw-r--r--hw/ide/internal.h171
-rw-r--r--hw/ide/piix.c7
-rw-r--r--hw/integratorcp.c28
-rw-r--r--hw/leon3.c15
-rw-r--r--hw/lm32_boards.c23
-rw-r--r--hw/mainstone.c20
-rw-r--r--hw/mcf5208.c72
-rw-r--r--hw/milkymist-minimac2.c43
-rw-r--r--hw/milkymist-softusb.c48
-rw-r--r--hw/milkymist.c13
-rw-r--r--hw/mips_fulong2e.c17
-rw-r--r--hw/mips_malta.c54
-rw-r--r--hw/mips_r4k.c13
-rw-r--r--hw/musicpal.c8
-rw-r--r--hw/omap_sx1.c8
-rw-r--r--hw/pci_host.c86
-rw-r--r--hw/pci_host.h16
-rw-r--r--hw/petalogix_ml605_mmu.c5
-rw-r--r--hw/petalogix_s3adsp1800_mmu.c5
-rw-r--r--hw/pflash_cfi01.c79
-rw-r--r--hw/pflash_cfi02.c96
-rw-r--r--hw/piix_pci.c13
-rw-r--r--hw/ppc405_boards.c49
-rw-r--r--hw/ppc4xx_pci.c10
-rw-r--r--hw/ppce500_pci.c21
-rw-r--r--hw/prep_pci.c12
-rw-r--r--hw/qdev-properties.c6
-rw-r--r--hw/r2d.c2
-rw-r--r--hw/scsi-bus.c6
-rw-r--r--hw/scsi-defs.h8
-rw-r--r--hw/scsi-disk.c157
-rw-r--r--hw/sd.c14
-rw-r--r--hw/sh_intc.c9
-rw-r--r--hw/spitz.c10
-rw-r--r--hw/stellaris.c5
-rw-r--r--hw/stellaris_enet.c29
-rw-r--r--hw/sysbus.c29
-rw-r--r--hw/sysbus.h8
-rw-r--r--hw/tosa.c10
-rw-r--r--hw/tusb6010.c11
-rw-r--r--hw/unin_pci.c82
-rw-r--r--hw/usb-bus.c110
-rw-r--r--hw/usb-ccid.c248
-rw-r--r--hw/usb-desc.h2
-rw-r--r--hw/usb-ehci.c65
-rw-r--r--hw/usb-hub.c12
-rw-r--r--hw/usb-msd.c2
-rw-r--r--hw/usb-musb.c26
-rw-r--r--hw/usb-ohci.c4
-rw-r--r--hw/usb-uhci.c11
-rw-r--r--hw/usb.c37
-rw-r--r--hw/usb.h11
-rw-r--r--hw/virtex_ml507.c4
-rw-r--r--hw/virtio-blk.c12
-rw-r--r--hw/xen_disk.c1
-rw-r--r--hw/z2.c2
75 files changed, 1520 insertions, 1090 deletions
diff --git a/hw/9pfs/codir.c b/hw/9pfs/codir.c
index 3a257b9027..f17f927c10 100644
--- a/hw/9pfs/codir.c
+++ b/hw/9pfs/codir.c
@@ -97,15 +97,19 @@ int v9fs_co_opendir(V9fsState *s, V9fsFidState *fidp)
                 err = 0;
             }
         });
+    if (!err) {
+        total_open_fd++;
+        if (total_open_fd > open_fd_hw) {
+            v9fs_reclaim_fd(s);
+        }
+    }
     return err;
 }
 
-int v9fs_co_closedir(V9fsState *s, V9fsFidState *fidp)
+int v9fs_co_closedir(V9fsState *s, DIR *dir)
 {
     int err;
-    DIR *dir;
 
-    dir = fidp->fs.dir;
     v9fs_co_run_in_worker(
         {
             err = s->ops->closedir(&s->ctx, dir);
@@ -113,5 +117,8 @@ int v9fs_co_closedir(V9fsState *s, V9fsFidState *fidp)
                 err = -errno;
             }
         });
+    if (!err) {
+        total_open_fd--;
+    }
     return err;
 }
diff --git a/hw/9pfs/cofile.c b/hw/9pfs/cofile.c
index e388146422..0caf1e3cee 100644
--- a/hw/9pfs/cofile.c
+++ b/hw/9pfs/cofile.c
@@ -58,6 +58,12 @@ int v9fs_co_open(V9fsState *s, V9fsFidState *fidp, int flags)
                 err = 0;
             }
         });
+    if (!err) {
+        total_open_fd++;
+        if (total_open_fd > open_fd_hw) {
+            v9fs_reclaim_fd(s);
+        }
+    }
     return err;
 }
 
@@ -79,15 +85,19 @@ int v9fs_co_open2(V9fsState *s, V9fsFidState *fidp, char *fullname, gid_t gid,
                 err = -errno;
             }
         });
+    if (!err) {
+        total_open_fd++;
+        if (total_open_fd > open_fd_hw) {
+            v9fs_reclaim_fd(s);
+        }
+    }
     return err;
 }
 
-int v9fs_co_close(V9fsState *s, V9fsFidState *fidp)
+int v9fs_co_close(V9fsState *s, int fd)
 {
-    int fd;
     int err;
 
-    fd = fidp->fs.fd;
     v9fs_co_run_in_worker(
         {
             err = s->ops->close(&s->ctx, fd);
@@ -95,6 +105,9 @@ int v9fs_co_close(V9fsState *s, V9fsFidState *fidp)
                 err = -errno;
             }
         });
+    if (!err) {
+        total_open_fd--;
+    }
     return err;
 }
 
diff --git a/hw/9pfs/virtio-9p-coth.h b/hw/9pfs/virtio-9p-coth.h
index 48defb72ff..b7be9b5f1f 100644
--- a/hw/9pfs/virtio-9p-coth.h
+++ b/hw/9pfs/virtio-9p-coth.h
@@ -83,8 +83,8 @@ extern int v9fs_co_open2(V9fsState *, V9fsFidState *, char *, gid_t, int, int);
 extern int v9fs_co_lsetxattr(V9fsState *, V9fsString *, V9fsString *,
                              void *, size_t, int);
 extern int v9fs_co_lremovexattr(V9fsState *, V9fsString *, V9fsString *);
-extern int v9fs_co_closedir(V9fsState *, V9fsFidState *);
-extern int v9fs_co_close(V9fsState *, V9fsFidState *);
+extern int v9fs_co_closedir(V9fsState *, DIR *);
+extern int v9fs_co_close(V9fsState *, int);
 extern int v9fs_co_fsync(V9fsState *, V9fsFidState *, int);
 extern int v9fs_co_symlink(V9fsState *, V9fsFidState *, const char *,
                            const char *, gid_t);
diff --git a/hw/9pfs/virtio-9p-device.c b/hw/9pfs/virtio-9p-device.c
index 94660024d6..97f2da5f0e 100644
--- a/hw/9pfs/virtio-9p-device.c
+++ b/hw/9pfs/virtio-9p-device.c
@@ -130,6 +130,7 @@ VirtIODevice *virtio_9p_init(DeviceState *dev, V9fsConf *conf)
     s->config_size = sizeof(struct virtio_9p_config) +
                         s->tag_len;
     s->vdev.get_config = virtio_9p_get_config;
+    s->fid_list = NULL;
 
     if (v9fs_init_worker_threads() < 0) {
         fprintf(stderr, "worker thread initialization failed\n");
@@ -171,6 +172,7 @@ static PCIDeviceInfo virtio_9p_info = {
 static void virtio_9p_register_devices(void)
 {
     pci_qdev_register(&virtio_9p_info);
+    virtio_9p_set_fd_limit();
 }
 
 device_init(virtio_9p_register_devices)
diff --git a/hw/9pfs/virtio-9p.c b/hw/9pfs/virtio-9p.c
index ad70768dce..94b7090e7d 100644
--- a/hw/9pfs/virtio-9p.c
+++ b/hw/9pfs/virtio-9p.c
@@ -22,6 +22,9 @@
 #include "virtio-9p-coth.h"
 
 int debug_9p_pdu;
+int open_fd_hw;
+int total_open_fd;
+static int open_fd_rc;
 
 enum {
     Oread   = 0x00,
@@ -232,16 +235,60 @@ static size_t v9fs_string_size(V9fsString *str)
     return str->size;
 }
 
-static V9fsFidState *lookup_fid(V9fsState *s, int32_t fid)
+/*
+ * returns 0 if fid got re-opened, 1 if not, < 0 on error */
+static int v9fs_reopen_fid(V9fsState *s, V9fsFidState *f)
+{
+    int err = 1;
+    if (f->fid_type == P9_FID_FILE) {
+        if (f->fs.fd == -1) {
+            do {
+                err = v9fs_co_open(s, f, f->open_flags);
+            } while (err == -EINTR);
+        }
+    } else if (f->fid_type == P9_FID_DIR) {
+        if (f->fs.dir == NULL) {
+            do {
+                err = v9fs_co_opendir(s, f);
+            } while (err == -EINTR);
+        }
+    }
+    return err;
+}
+
+static V9fsFidState *get_fid(V9fsState *s, int32_t fid)
 {
+    int err;
     V9fsFidState *f;
 
     for (f = s->fid_list; f; f = f->next) {
+        BUG_ON(f->clunked);
         if (f->fid == fid) {
+            /*
+             * Update the fid ref upfront so that
+             * we don't get reclaimed when we yield
+             * in open later.
+             */
+            f->ref++;
+            /*
+             * check whether we need to reopen the
+             * file. We might have closed the fd
+             * while trying to free up some file
+             * descriptors.
+             */
+            err = v9fs_reopen_fid(s, f);
+            if (err < 0) {
+                f->ref--;
+                return NULL;
+            }
+            /*
+             * Mark the fid as referenced so that the LRU
+             * reclaim won't close the file descriptor
+             */
+            f->flags |= FID_REFERENCED;
             return f;
         }
     }
-
     return NULL;
 }
 
@@ -249,16 +296,22 @@ static V9fsFidState *alloc_fid(V9fsState *s, int32_t fid)
 {
     V9fsFidState *f;
 
-    f = lookup_fid(s, fid);
-    if (f) {
-        return NULL;
+    for (f = s->fid_list; f; f = f->next) {
+        /* If fid is already there return NULL */
+        BUG_ON(f->clunked);
+        if (f->fid == fid) {
+            return NULL;
+        }
     }
-
     f = g_malloc0(sizeof(V9fsFidState));
-
     f->fid = fid;
     f->fid_type = P9_FID_NONE;
-
+    f->ref = 1;
+    /*
+     * Mark the fid as referenced so that the LRU
+     * reclaim won't close the file descriptor
+     */
+    f->flags |= FID_REFERENCED;
     f->next = s->fid_list;
     s->fid_list = f;
 
@@ -299,9 +352,41 @@ free_value:
     return retval;
 }
 
-static int free_fid(V9fsState *s, int32_t fid)
+static int free_fid(V9fsState *s, V9fsFidState *fidp)
 {
     int retval = 0;
+
+    if (fidp->fid_type == P9_FID_FILE) {
+        /* If we reclaimed the fd no need to close */
+        if (fidp->fs.fd != -1) {
+            retval = v9fs_co_close(s, fidp->fs.fd);
+        }
+    } else if (fidp->fid_type == P9_FID_DIR) {
+        if (fidp->fs.dir != NULL) {
+            retval = v9fs_co_closedir(s, fidp->fs.dir);
+        }
+    } else if (fidp->fid_type == P9_FID_XATTR) {
+        retval = v9fs_xattr_fid_clunk(s, fidp);
+    }
+    v9fs_string_free(&fidp->path);
+    g_free(fidp);
+    return retval;
+}
+
+static void put_fid(V9fsState *s, V9fsFidState *fidp)
+{
+    BUG_ON(!fidp->ref);
+    fidp->ref--;
+    /*
+     * Don't free the fid if it is in reclaim list
+     */
+    if (!fidp->ref && fidp->clunked) {
+        free_fid(s, fidp);
+    }
+}
+
+static int clunk_fid(V9fsState *s, int32_t fid)
+{
     V9fsFidState **fidpp, *fidp;
 
     for (fidpp = &s->fid_list; *fidpp; fidpp = &(*fidpp)->next) {
@@ -313,20 +398,119 @@ static int free_fid(V9fsState *s, int32_t fid)
     if (*fidpp == NULL) {
         return -ENOENT;
     }
-
     fidp = *fidpp;
     *fidpp = fidp->next;
+    fidp->clunked = 1;
+    return 0;
+}
 
-    if (fidp->fid_type == P9_FID_FILE) {
-        retval = v9fs_co_close(s, fidp);
-    } else if (fidp->fid_type == P9_FID_DIR) {
-        retval = v9fs_co_closedir(s, fidp);
-    } else if (fidp->fid_type == P9_FID_XATTR) {
-        retval = v9fs_xattr_fid_clunk(s, fidp);
+void v9fs_reclaim_fd(V9fsState *s)
+{
+    int reclaim_count = 0;
+    V9fsFidState *f, *reclaim_list = NULL;
+
+    for (f = s->fid_list; f; f = f->next) {
+        /*
+         * Unlink fids cannot be reclaimed. Check
+         * for them and skip them. Also skip fids
+         * currently being operated on.
+         */
+        if (f->ref || f->flags & FID_NON_RECLAIMABLE) {
+            continue;
+        }
+        /*
+         * if it is a recently referenced fid
+         * we leave the fid untouched and clear the
+         * reference bit. We come back to it later
+         * in the next iteration. (a simple LRU without
+         * moving list elements around)
+         */
+        if (f->flags & FID_REFERENCED) {
+            f->flags &= ~FID_REFERENCED;
+            continue;
+        }
+        /*
+         * Add fids to reclaim list.
+         */
+        if (f->fid_type == P9_FID_FILE) {
+            if (f->fs.fd != -1) {
+                /*
+                 * Up the reference count so that
+                 * a clunk request won't free this fid
+                 */
+                f->ref++;
+                f->rclm_lst = reclaim_list;
+                reclaim_list = f;
+                f->fs_reclaim.fd = f->fs.fd;
+                f->fs.fd = -1;
+                reclaim_count++;
+            }
+        } else if (f->fid_type == P9_FID_DIR) {
+            if (f->fs.dir != NULL) {
+                /*
+                 * Up the reference count so that
+                 * a clunk request won't free this fid
+                 */
+                f->ref++;
+                f->rclm_lst = reclaim_list;
+                reclaim_list = f;
+                f->fs_reclaim.dir = f->fs.dir;
+                f->fs.dir = NULL;
+                reclaim_count++;
+            }
+        }
+        if (reclaim_count >= open_fd_rc) {
+            break;
+        }
+    }
+    /*
+     * Now close the fid in reclaim list. Free them if they
+     * are already clunked.
+     */
+    while (reclaim_list) {
+        f = reclaim_list;
+        reclaim_list = f->rclm_lst;
+        if (f->fid_type == P9_FID_FILE) {
+            v9fs_co_close(s, f->fs_reclaim.fd);
+        } else if (f->fid_type == P9_FID_DIR) {
+            v9fs_co_closedir(s, f->fs_reclaim.dir);
+        }
+        f->rclm_lst = NULL;
+        /*
+         * Now drop the fid reference, free it
+         * if clunked.
+         */
+        put_fid(s, f);
     }
-    v9fs_string_free(&fidp->path);
-    g_free(fidp);
-    return retval;
+}
+
+static int v9fs_mark_fids_unreclaim(V9fsState *s, V9fsString *str)
+{
+    int err;
+    V9fsFidState *fidp, head_fid;
+
+    head_fid.next = s->fid_list;
+    for (fidp = s->fid_list; fidp; fidp = fidp->next) {
+        if (!strcmp(fidp->path.data, str->data)) {
+            /* Mark the fid non reclaimable. */
+            fidp->flags |= FID_NON_RECLAIMABLE;
+
+            /* reopen the file/dir if already closed */
+            err = v9fs_reopen_fid(s, fidp);
+            if (err < 0) {
+                return -1;
+            }
+            /*
+             * Go back to head of fid list because
+             * the list could have got updated when
+             * switched to the worker thread
+             */
+            if (err == 0) {
+                fidp = &head_fid;
+            }
+        }
+    }
+    return 0;
 }
 
 #define P9_QID_TYPE_DIR         0x80
@@ -1014,19 +1198,21 @@ static void v9fs_attach(void *opaque)
     fidp = alloc_fid(s, fid);
     if (fidp == NULL) {
         err = -EINVAL;
-        goto out;
+        goto out_nofid;
     }
     fidp->uid = n_uname;
     v9fs_string_sprintf(&fidp->path, "%s", "/");
     err = fid_to_qid(s, fidp, &qid);
     if (err < 0) {
         err = -EINVAL;
-        free_fid(s, fid);
+        clunk_fid(s, fid);
         goto out;
     }
     offset += pdu_marshal(pdu, offset, "Q", &qid);
     err = offset;
 out:
+    put_fid(s, fidp);
+out_nofid:
     complete_pdu(s, pdu, err);
     v9fs_string_free(&uname);
     v9fs_string_free(&aname);
@@ -1044,10 +1230,11 @@ static void v9fs_stat(void *opaque)
     V9fsState *s = pdu->s;
 
     pdu_unmarshal(pdu, offset, "d", &fid);
-    fidp = lookup_fid(s, fid);
+
+    fidp = get_fid(s, fid);
     if (fidp == NULL) {
         err = -ENOENT;
-        goto out;
+        goto out_nofid;
     }
     err = v9fs_co_lstat(s, &fidp->path, &stbuf);
     if (err < 0) {
@@ -1061,6 +1248,8 @@ static void v9fs_stat(void *opaque)
     err = offset;
     v9fs_stat_free(&v9stat);
 out:
+    put_fid(s, fidp);
+out_nofid:
     complete_pdu(s, pdu, err);
 }
 
@@ -1078,10 +1267,10 @@ static void v9fs_getattr(void *opaque)
 
     pdu_unmarshal(pdu, offset, "dq", &fid, &request_mask);
 
-    fidp = lookup_fid(s, fid);
+    fidp = get_fid(s, fid);
     if (fidp == NULL) {
         retval = -ENOENT;
-        goto out;
+        goto out_nofid;
     }
     /*
      * Currently we only support BASIC fields in stat, so there is no
@@ -1095,6 +1284,8 @@ static void v9fs_getattr(void *opaque)
     retval = offset;
     retval += pdu_marshal(pdu, offset, "A", &v9stat_dotl);
 out:
+    put_fid(s, fidp);
+out_nofid:
     complete_pdu(s, pdu, retval);
 }
 
@@ -1122,10 +1313,10 @@ static void v9fs_setattr(void *opaque)
 
     pdu_unmarshal(pdu, offset, "dI", &fid, &v9iattr);
 
-    fidp = lookup_fid(s, fid);
+    fidp = get_fid(s, fid);
     if (fidp == NULL) {
         err = -EINVAL;
-        goto out;
+        goto out_nofid;
     }
     if (v9iattr.valid & ATTR_MODE) {
         err = v9fs_co_chmod(s, &fidp->path, v9iattr.mode);
@@ -1187,6 +1378,8 @@ static void v9fs_setattr(void *opaque)
     }
     err = offset;
 out:
+    put_fid(s, fidp);
+out_nofid:
     complete_pdu(s, pdu, err);
 }
 
@@ -1213,7 +1406,7 @@ static void v9fs_walk(void *opaque)
     int32_t fid, newfid;
     V9fsString *wnames = NULL;
     V9fsFidState *fidp;
-    V9fsFidState *newfidp;
+    V9fsFidState *newfidp = NULL;;
     V9fsPDU *pdu = opaque;
     V9fsState *s = pdu->s;
 
@@ -1229,12 +1422,12 @@ static void v9fs_walk(void *opaque)
 
     } else if (nwnames > P9_MAXWELEM) {
         err = -EINVAL;
-        goto out;
+        goto out_nofid;
     }
-    fidp = lookup_fid(s, fid);
+    fidp = get_fid(s, fid);
     if (fidp == NULL) {
         err = -ENOENT;
-        goto out;
+        goto out_nofid;
     }
     if (fid == newfid) {
         BUG_ON(fidp->fid_type != P9_FID_NONE);
@@ -1267,7 +1460,7 @@ static void v9fs_walk(void *opaque)
             v9fs_string_copy(&newfidp->path, &path);
             err = v9fs_co_lstat(s, &newfidp->path, &stbuf);
             if (err < 0) {
-                free_fid(s, newfidp->fid);
+                clunk_fid(s, newfidp->fid);
                 v9fs_string_free(&path);
                 goto out;
             }
@@ -1277,6 +1470,11 @@ static void v9fs_walk(void *opaque)
     }
     err = v9fs_walk_marshal(pdu, nwnames, qids);
 out:
+    put_fid(s, fidp);
+    if (newfidp) {
+        put_fid(s, newfidp);
+    }
+out_nofid:
     complete_pdu(s, pdu, err);
     if (nwnames && nwnames <= P9_MAXWELEM) {
         for (name_idx = 0; name_idx < nwnames; name_idx++) {
@@ -1325,10 +1523,10 @@ static void v9fs_open(void *opaque)
     } else {
         pdu_unmarshal(pdu, offset, "db", &fid, &mode);
     }
-    fidp = lookup_fid(s, fid);
+    fidp = get_fid(s, fid);
     if (fidp == NULL) {
         err = -ENOENT;
-        goto out;
+        goto out_nofid;
     }
     BUG_ON(fidp->fid_type != P9_FID_NONE);
 
@@ -1359,11 +1557,21 @@ static void v9fs_open(void *opaque)
             goto out;
         }
         fidp->fid_type = P9_FID_FILE;
+        fidp->open_flags = flags;
+        if (flags & O_EXCL) {
+            /*
+             * We let the host file system do O_EXCL check
+             * We should not reclaim such fd
+             */
+            fidp->flags |= FID_NON_RECLAIMABLE;
+        }
         iounit = get_iounit(s, &fidp->path);
         offset += pdu_marshal(pdu, offset, "Qd", &qid, iounit);
         err = offset;
     }
 out:
+    put_fid(s, fidp);
+out_nofid:
     complete_pdu(s, pdu, err);
 }
 
@@ -1385,10 +1593,10 @@ static void v9fs_lcreate(void *opaque)
     pdu_unmarshal(pdu, offset, "dsddd", &dfid, &name, &flags,
                   &mode, &gid);
 
-    fidp = lookup_fid(pdu->s, dfid);
+    fidp = get_fid(pdu->s, dfid);
     if (fidp == NULL) {
         err = -ENOENT;
-        goto out;
+        goto out_nofid;
     }
     v9fs_string_sprintf(&fullname, "%s/%s", fidp->path.data, name.data);
 
@@ -1400,13 +1608,21 @@ static void v9fs_lcreate(void *opaque)
         goto out;
     }
     fidp->fid_type = P9_FID_FILE;
+    fidp->open_flags = flags;
+    if (flags & O_EXCL) {
+        /*
+         * We let the host file system do O_EXCL check
+         * We should not reclaim such fd
+         */
+        fidp->flags |= FID_NON_RECLAIMABLE;
+    }
     iounit =  get_iounit(pdu->s, &fullname);
 
     err = v9fs_co_lstat(pdu->s, &fullname, &stbuf);
     if (err < 0) {
         fidp->fid_type = P9_FID_NONE;
         if (fidp->fs.fd > 0) {
-            close(fidp->fs.fd);
+            v9fs_co_close(pdu->s, fidp->fs.fd);
         }
         goto out;
     }
@@ -1415,6 +1631,8 @@ static void v9fs_lcreate(void *opaque)
     offset += pdu_marshal(pdu, offset, "Qd", &qid, iounit);
     err = offset;
 out:
+    put_fid(pdu->s, fidp);
+out_nofid:
     complete_pdu(pdu->s, pdu, err);
     v9fs_string_free(&name);
     v9fs_string_free(&fullname);
@@ -1431,16 +1649,17 @@ static void v9fs_fsync(void *opaque)
     V9fsState *s = pdu->s;
 
     pdu_unmarshal(pdu, offset, "dd", &fid, &datasync);
-    fidp = lookup_fid(s, fid);
+    fidp = get_fid(s, fid);
     if (fidp == NULL) {
         err = -ENOENT;
-        goto out;
+        goto out_nofid;
     }
     err = v9fs_co_fsync(s, fidp, datasync);
     if (!err) {
         err = offset;
     }
-out:
+    put_fid(s, fidp);
+out_nofid:
     complete_pdu(s, pdu, err);
 }
 
@@ -1449,16 +1668,25 @@ static void v9fs_clunk(void *opaque)
     int err;
     int32_t fid;
     size_t offset = 7;
+    V9fsFidState *fidp;
     V9fsPDU *pdu = opaque;
     V9fsState *s = pdu->s;
 
     pdu_unmarshal(pdu, offset, "d", &fid);
-    err = free_fid(s, fid);
+
+    fidp = get_fid(s, fid);
+    if (fidp == NULL) {
+        err = -ENOENT;
+        goto out_nofid;
+    }
+    err = clunk_fid(s, fidp->fid);
     if (err < 0) {
         goto out;
     }
     err = offset;
 out:
+    put_fid(s, fidp);
+out_nofid:
     complete_pdu(s, pdu, err);
 }
 
@@ -1557,10 +1785,11 @@ static void v9fs_read(void *opaque)
     V9fsState *s = pdu->s;
 
     pdu_unmarshal(pdu, offset, "dqd", &fid, &off, &max_count);
-    fidp = lookup_fid(s, fid);
+
+    fidp = get_fid(s, fid);
     if (fidp == NULL) {
         err = -EINVAL;
-        goto out;
+        goto out_nofid;
     }
     if (fidp->fid_type == P9_FID_DIR) {
 
@@ -1612,6 +1841,8 @@ static void v9fs_read(void *opaque)
         err = -EINVAL;
     }
 out:
+    put_fid(s, fidp);
+out_nofid:
     complete_pdu(s, pdu, err);
 }
 
@@ -1696,8 +1927,12 @@ static void v9fs_readdir(void *opaque)
 
     pdu_unmarshal(pdu, offset, "dqd", &fid, &initial_offset, &max_count);
 
-    fidp = lookup_fid(s, fid);
-    if (fidp == NULL || !fidp->fs.dir) {
+    fidp = get_fid(s, fid);
+    if (fidp == NULL) {
+        retval = -EINVAL;
+        goto out_nofid;
+    }
+    if (!fidp->fs.dir) {
         retval = -EINVAL;
         goto out;
     }
@@ -1715,6 +1950,8 @@ static void v9fs_readdir(void *opaque)
     retval += pdu_marshal(pdu, offset, "d", count);
     retval += count;
 out:
+    put_fid(s, fidp);
+out_nofid:
     complete_pdu(s, pdu, retval);
 }
 
@@ -1779,10 +2016,11 @@ static void v9fs_write(void *opaque)
     V9fsState *s = pdu->s;
 
     pdu_unmarshal(pdu, offset, "dqdv", &fid, &off, &count, sg, &cnt);
-    fidp = lookup_fid(s, fid);
+
+    fidp = get_fid(s, fid);
     if (fidp == NULL) {
         err = -EINVAL;
-        goto out;
+        goto out_nofid;
     }
     if (fidp->fid_type == P9_FID_FILE) {
         if (fidp->fs.fd == -1) {
@@ -1822,6 +2060,8 @@ static void v9fs_write(void *opaque)
     offset += pdu_marshal(pdu, offset, "d", total);
     err = offset;
 out:
+    put_fid(s, fidp);
+out_nofid:
     complete_pdu(s, pdu, err);
 }
 
@@ -1846,10 +2086,10 @@ static void v9fs_create(void *opaque)
     pdu_unmarshal(pdu, offset, "dsdbs", &fid, &name,
                   &perm, &mode, &extension);
 
-    fidp = lookup_fid(pdu->s, fid);
+    fidp = get_fid(pdu->s, fid);
     if (fidp == NULL) {
         err = -EINVAL;
-        goto out;
+        goto out_nofid;
     }
 
     v9fs_string_sprintf(&fullname, "%s/%s", fidp->path.data, name.data);
@@ -1879,15 +2119,17 @@ static void v9fs_create(void *opaque)
         }
     } else if (perm & P9_STAT_MODE_LINK) {
         int32_t nfid = atoi(extension.data);
-        V9fsFidState *nfidp = lookup_fid(pdu->s, nfid);
+        V9fsFidState *nfidp = get_fid(pdu->s, nfid);
         if (nfidp == NULL) {
             err = -EINVAL;
             goto out;
         }
         err = v9fs_co_link(pdu->s, &nfidp->path, &fullname);
         if (err < 0) {
+            put_fid(pdu->s, nfidp);
             goto out;
         }
+        put_fid(pdu->s, nfidp);
     } else if (perm & P9_STAT_MODE_DEVICE) {
         char ctype;
         uint32_t major, minor;
@@ -1935,12 +2177,20 @@ static void v9fs_create(void *opaque)
             goto out;
         }
         fidp->fid_type = P9_FID_FILE;
+        fidp->open_flags = omode_to_uflags(mode);
+        if (fidp->open_flags & O_EXCL) {
+            /*
+             * We let the host file system do O_EXCL check
+             * We should not reclaim such fd
+             */
+            fidp->flags |= FID_NON_RECLAIMABLE;
+        }
     }
     err = v9fs_co_lstat(pdu->s, &fullname, &stbuf);
     if (err < 0) {
         fidp->fid_type = P9_FID_NONE;
         if (fidp->fs.fd) {
-            close(fidp->fs.fd);
+            v9fs_co_close(pdu->s, fidp->fs.fd);
         }
         goto out;
     }
@@ -1950,6 +2200,8 @@ static void v9fs_create(void *opaque)
     offset += pdu_marshal(pdu, offset, "Qd", &qid, iounit);
     err = offset;
 out:
+    put_fid(pdu->s, fidp);
+out_nofid:
    complete_pdu(pdu->s, pdu, err);
    v9fs_string_free(&name);
    v9fs_string_free(&extension);
@@ -1973,10 +2225,10 @@ static void v9fs_symlink(void *opaque)
     v9fs_string_init(&fullname);
     pdu_unmarshal(pdu, offset, "dssd", &dfid, &name, &symname, &gid);
 
-    dfidp = lookup_fid(pdu->s, dfid);
+    dfidp = get_fid(pdu->s, dfid);
     if (dfidp == NULL) {
         err = -EINVAL;
-        goto out;
+        goto out_nofid;
     }
 
     v9fs_string_sprintf(&fullname, "%s/%s", dfidp->path.data, name.data);
@@ -1992,6 +2244,8 @@ static void v9fs_symlink(void *opaque)
     offset += pdu_marshal(pdu, offset, "Q", &qid);
     err = offset;
 out:
+    put_fid(pdu->s, dfidp);
+out_nofid:
     complete_pdu(pdu->s, pdu, err);
     v9fs_string_free(&name);
     v9fs_string_free(&symname);
@@ -2021,13 +2275,13 @@ static void v9fs_link(void *opaque)
 
     pdu_unmarshal(pdu, offset, "dds", &dfid, &oldfid, &name);
 
-    dfidp = lookup_fid(s, dfid);
+    dfidp = get_fid(s, dfid);
     if (dfidp == NULL) {
         err = -ENOENT;
-        goto out;
+        goto out_nofid;
     }
 
-    oldfidp = lookup_fid(s, oldfid);
+    oldfidp = get_fid(s, oldfid);
     if (oldfidp == NULL) {
         err = -ENOENT;
         goto out;
@@ -2041,6 +2295,8 @@ static void v9fs_link(void *opaque)
     v9fs_string_free(&fullname);
 
 out:
+    put_fid(s, dfidp);
+out_nofid:
     v9fs_string_free(&name);
     complete_pdu(s, pdu, err);
 }
@@ -2055,19 +2311,28 @@ static void v9fs_remove(void *opaque)
 
     pdu_unmarshal(pdu, offset, "d", &fid);
 
-    fidp = lookup_fid(pdu->s, fid);
+    fidp = get_fid(pdu->s, fid);
     if (fidp == NULL) {
         err = -EINVAL;
-        goto out;
+        goto out_nofid;
+    }
+    /*
+     * IF the file is unlinked, we cannot reopen
+     * the file later. So don't reclaim fd
+     */
+    err = v9fs_mark_fids_unreclaim(pdu->s, &fidp->path);
+    if (err < 0) {
+        goto out_err;
     }
     err = v9fs_co_remove(pdu->s, &fidp->path);
     if (!err) {
         err = offset;
     }
-
+out_err:
     /* For TREMOVE we need to clunk the fid even on failed remove */
-    free_fid(pdu->s, fidp->fid);
-out:
+    clunk_fid(pdu->s, fidp->fid);
+    put_fid(pdu->s, fidp);
+out_nofid:
     complete_pdu(pdu->s, pdu, err);
 }
 
@@ -2076,14 +2341,14 @@ static int v9fs_complete_rename(V9fsState *s, V9fsFidState *fidp,
 {
     char *end;
     int err = 0;
+    V9fsFidState *dirfidp = NULL;
     char *old_name, *new_name;
 
     if (newdirfid != -1) {
-        V9fsFidState *dirfidp;
-        dirfidp = lookup_fid(s, newdirfid);
+        dirfidp = get_fid(s, newdirfid);
         if (dirfidp == NULL) {
             err = -ENOENT;
-            goto out;
+            goto out_nofid;
         }
         BUG_ON(dirfidp->fid_type != P9_FID_NONE);
 
@@ -2136,6 +2401,10 @@ static int v9fs_complete_rename(V9fsState *s, V9fsFidState *fidp,
         v9fs_string_copy(&fidp->path, name);
     }
 out:
+    if (dirfidp) {
+        put_fid(s, dirfidp);
+    }
+out_nofid:
     return err;
 }
 
@@ -2152,10 +2421,10 @@ static void v9fs_rename(void *opaque)
 
     pdu_unmarshal(pdu, offset, "dds", &fid, &newdirfid, &name);
 
-    fidp = lookup_fid(s, fid);
+    fidp = get_fid(s, fid);
     if (fidp == NULL) {
         err = -ENOENT;
-        goto out;
+        goto out_nofid;
     }
     BUG_ON(fidp->fid_type != P9_FID_NONE);
 
@@ -2163,7 +2432,8 @@ static void v9fs_rename(void *opaque)
     if (!err) {
         err = offset;
     }
-out:
+    put_fid(s, fidp);
+out_nofid:
     complete_pdu(s, pdu, err);
     v9fs_string_free(&name);
 }
@@ -2181,10 +2451,11 @@ static void v9fs_wstat(void *opaque)
     V9fsState *s = pdu->s;
 
     pdu_unmarshal(pdu, offset, "dwS", &fid, &unused, &v9stat);
-    fidp = lookup_fid(s, fid);
+
+    fidp = get_fid(s, fid);
     if (fidp == NULL) {
         err = -EINVAL;
-        goto out;
+        goto out_nofid;
     }
     /* do we need to sync the file? */
     if (donttouch_stat(&v9stat)) {
@@ -2250,6 +2521,8 @@ static void v9fs_wstat(void *opaque)
     }
     err = offset;
 out:
+    put_fid(s, fidp);
+out_nofid:
     v9fs_stat_free(&v9stat);
     complete_pdu(s, pdu, err);
 }
@@ -2310,10 +2583,10 @@ static void v9fs_statfs(void *opaque)
     V9fsState *s = pdu->s;
 
     pdu_unmarshal(pdu, offset, "d", &fid);
-    fidp = lookup_fid(s, fid);
+    fidp = get_fid(s, fid);
     if (fidp == NULL) {
         retval = -ENOENT;
-        goto out;
+        goto out_nofid;
     }
     retval = v9fs_co_statfs(s, &fidp->path, &stbuf);
     if (retval < 0) {
@@ -2322,6 +2595,8 @@ static void v9fs_statfs(void *opaque)
     retval = offset;
     retval += v9fs_fill_statfs(s, pdu, &stbuf);
 out:
+    put_fid(s, fidp);
+out_nofid:
     complete_pdu(s, pdu, retval);
     return;
 }
@@ -2347,10 +2622,10 @@ static void v9fs_mknod(void *opaque)
     pdu_unmarshal(pdu, offset, "dsdddd", &fid, &name, &mode,
                   &major, &minor, &gid);
 
-    fidp = lookup_fid(s, fid);
+    fidp = get_fid(s, fid);
     if (fidp == NULL) {
         err = -ENOENT;
-        goto out;
+        goto out_nofid;
     }
     v9fs_string_sprintf(&fullname, "%s/%s", fidp->path.data, name.data);
     err = v9fs_co_mknod(s, &fullname, fidp->uid, gid,
@@ -2366,6 +2641,8 @@ static void v9fs_mknod(void *opaque)
     err = offset;
     err += pdu_marshal(pdu, offset, "Q", &qid);
 out:
+    put_fid(s, fidp);
+out_nofid:
     complete_pdu(s, pdu, err);
     v9fs_string_free(&fullname);
     v9fs_string_free(&name);
@@ -2399,12 +2676,12 @@ static void v9fs_lock(void *opaque)
     /* We support only block flag now (that too ignored currently) */
     if (flock->flags & ~P9_LOCK_FLAGS_BLOCK) {
         err = -EINVAL;
-        goto out;
+        goto out_nofid;
     }
-    fidp = lookup_fid(s, fid);
+    fidp = get_fid(s, fid);
     if (fidp == NULL) {
         err = -ENOENT;
-        goto out;
+        goto out_nofid;
     }
     err = v9fs_co_fstat(s, fidp->fs.fd, &stbuf);
     if (err < 0) {
@@ -2412,6 +2689,8 @@ static void v9fs_lock(void *opaque)
     }
     status = P9_LOCK_SUCCESS;
 out:
+    put_fid(s, fidp);
+out_nofid:
     err = offset;
     err += pdu_marshal(pdu, offset, "b", status);
     complete_pdu(s, pdu, err);
@@ -2437,10 +2716,10 @@ static void v9fs_getlock(void *opaque)
                   &glock->start, &glock->length, &glock->proc_id,
                   &glock->client_id);
 
-    fidp = lookup_fid(s, fid);
+    fidp = get_fid(s, fid);
     if (fidp == NULL) {
         err = -ENOENT;
-        goto out;
+        goto out_nofid;
     }
     err = v9fs_co_fstat(s, fidp->fs.fd, &stbuf);
     if (err < 0) {
@@ -2452,6 +2731,8 @@ static void v9fs_getlock(void *opaque)
                           &glock->client_id);
     err = offset;
 out:
+    put_fid(s, fidp);
+out_nofid:
     complete_pdu(s, pdu, err);
     g_free(glock);
 }
@@ -2472,10 +2753,10 @@ static void v9fs_mkdir(void *opaque)
     v9fs_string_init(&fullname);
     pdu_unmarshal(pdu, offset, "dsdd", &fid, &name, &mode, &gid);
 
-    fidp = lookup_fid(pdu->s, fid);
+    fidp = get_fid(pdu->s, fid);
     if (fidp == NULL) {
         err = -ENOENT;
-        goto out;
+        goto out_nofid;
     }
     v9fs_string_sprintf(&fullname, "%s/%s", fidp->path.data, name.data);
     err = v9fs_co_mkdir(pdu->s, fullname.data, mode, fidp->uid, gid);
@@ -2490,6 +2771,8 @@ static void v9fs_mkdir(void *opaque)
     offset += pdu_marshal(pdu, offset, "Q", &qid);
     err = offset;
 out:
+    put_fid(pdu->s, fidp);
+out_nofid:
     complete_pdu(pdu->s, pdu, err);
     v9fs_string_free(&fullname);
     v9fs_string_free(&name);
@@ -2503,15 +2786,15 @@ static void v9fs_xattrwalk(void *opaque)
     size_t offset = 7;
     int32_t fid, newfid;
     V9fsFidState *file_fidp;
-    V9fsFidState *xattr_fidp;
+    V9fsFidState *xattr_fidp = NULL;
     V9fsPDU *pdu = opaque;
     V9fsState *s = pdu->s;
 
     pdu_unmarshal(pdu, offset, "dds", &fid, &newfid, &name);
-    file_fidp = lookup_fid(s, fid);
+    file_fidp = get_fid(s, fid);
     if (file_fidp == NULL) {
         err = -ENOENT;
-        goto out;
+        goto out_nofid;
     }
     xattr_fidp = alloc_fid(s, newfid);
     if (xattr_fidp == NULL) {
@@ -2526,7 +2809,7 @@ static void v9fs_xattrwalk(void *opaque)
         size = v9fs_co_llistxattr(s, &xattr_fidp->path, NULL, 0);
         if (size < 0) {
             err = size;
-            free_fid(s, xattr_fidp->fid);
+            clunk_fid(s, xattr_fidp->fid);
             goto out;
         }
         /*
@@ -2541,7 +2824,7 @@ static void v9fs_xattrwalk(void *opaque)
                                      xattr_fidp->fs.xattr.value,
                                      xattr_fidp->fs.xattr.len);
             if (err < 0) {
-                free_fid(s, xattr_fidp->fid);
+                clunk_fid(s, xattr_fidp->fid);
                 goto out;
             }
         }
@@ -2556,7 +2839,7 @@ static void v9fs_xattrwalk(void *opaque)
                                  &name, NULL, 0);
         if (size < 0) {
             err = size;
-            free_fid(s, xattr_fidp->fid);
+            clunk_fid(s, xattr_fidp->fid);
             goto out;
         }
         /*
@@ -2571,7 +2854,7 @@ static void v9fs_xattrwalk(void *opaque)
                                     &name, xattr_fidp->fs.xattr.value,
                                     xattr_fidp->fs.xattr.len);
             if (err < 0) {
-                free_fid(s, xattr_fidp->fid);
+                clunk_fid(s, xattr_fidp->fid);
                 goto out;
             }
         }
@@ -2579,6 +2862,11 @@ static void v9fs_xattrwalk(void *opaque)
         err = offset;
     }
 out:
+    put_fid(s, file_fidp);
+    if (xattr_fidp) {
+        put_fid(s, xattr_fidp);
+    }
+out_nofid:
     complete_pdu(s, pdu, err);
     v9fs_string_free(&name);
 }
@@ -2599,10 +2887,10 @@ static void v9fs_xattrcreate(void *opaque)
     pdu_unmarshal(pdu, offset, "dsqd",
                   &fid, &name, &size, &flags);
 
-    file_fidp = lookup_fid(s, fid);
+    file_fidp = get_fid(s, fid);
     if (file_fidp == NULL) {
         err = -EINVAL;
-        goto out;
+        goto out_nofid;
     }
     /* Make the file fid point to xattr */
     xattr_fidp = file_fidp;
@@ -2618,7 +2906,8 @@ static void v9fs_xattrcreate(void *opaque)
         xattr_fidp->fs.xattr.value = NULL;
     }
     err = offset;
-out:
+    put_fid(s, file_fidp);
+out_nofid:
     complete_pdu(s, pdu, err);
     v9fs_string_free(&name);
 }
@@ -2633,10 +2922,10 @@ static void v9fs_readlink(void *opaque)
     V9fsFidState *fidp;
 
     pdu_unmarshal(pdu, offset, "d", &fid);
-    fidp = lookup_fid(pdu->s, fid);
+    fidp = get_fid(pdu->s, fid);
     if (fidp == NULL) {
         err = -ENOENT;
-        goto out;
+        goto out_nofid;
     }
 
     v9fs_string_init(&target);
@@ -2648,6 +2937,8 @@ static void v9fs_readlink(void *opaque)
     err = offset;
     v9fs_string_free(&target);
 out:
+    put_fid(pdu->s, fidp);
+out_nofid:
     complete_pdu(pdu->s, pdu, err);
 }
 
@@ -2732,3 +3023,14 @@ void handle_9p_output(VirtIODevice *vdev, VirtQueue *vq)
     }
     free_pdu(s, pdu);
 }
+
+void virtio_9p_set_fd_limit(void)
+{
+    struct rlimit rlim;
+    if (getrlimit(RLIMIT_NOFILE, &rlim) < 0) {
+        fprintf(stderr, "Failed to get the resource limit\n");
+        exit(1);
+    }
+    open_fd_hw = rlim.rlim_cur - MIN(400, rlim.rlim_cur/3);
+    open_fd_rc = rlim.rlim_cur/2;
+}
diff --git a/hw/9pfs/virtio-9p.h b/hw/9pfs/virtio-9p.h
index d00a502dcc..9d1b508e16 100644
--- a/hw/9pfs/virtio-9p.h
+++ b/hw/9pfs/virtio-9p.h
@@ -5,6 +5,7 @@
 #include <dirent.h>
 #include <sys/time.h>
 #include <utime.h>
+#include <sys/resource.h>
 #include "hw/virtio.h"
 #include "fsdev/file-op-9p.h"
 
@@ -101,6 +102,9 @@ enum p9_proto_version {
 #define P9_NOTAG    (u16)(~0)
 #define P9_NOFID    (u32)(~0)
 #define P9_MAXWELEM 16
+
+#define FID_REFERENCED          0x1
+#define FID_NON_RECLAIMABLE     0x2
 static inline const char *rpath(FsContext *ctx, const char *path, char *buffer)
 {
     snprintf(buffer, PATH_MAX, "%s/%s", ctx->fs_root, path);
@@ -198,12 +202,21 @@ struct V9fsFidState
     int32_t fid;
     V9fsString path;
     union {
-	int fd;
-	DIR *dir;
-	V9fsXattr xattr;
+        int fd;
+        DIR *dir;
+        V9fsXattr xattr;
     } fs;
+    union {
+        int fd;
+        DIR *dir;
+    } fs_reclaim;
+    int flags;
+    int open_flags;
     uid_t uid;
+    int ref;
+    int clunked;
     V9fsFidState *next;
+    V9fsFidState *rclm_lst;
 };
 
 typedef struct V9fsState
@@ -352,6 +365,9 @@ typedef struct V9fsGetlock
     V9fsString client_id;
 } V9fsGetlock;
 
+extern int open_fd_hw;
+extern int total_open_fd;
+
 size_t pdu_packunpack(void *addr, struct iovec *sg, int sg_count,
                       size_t offset, size_t size, int pack);
 
@@ -362,4 +378,6 @@ static inline size_t do_pdu_unpack(void *dst, struct iovec *sg, int sg_count,
 }
 
 extern void handle_9p_output(VirtIODevice *vdev, VirtQueue *vq);
+extern void virtio_9p_set_fd_limit(void);
+extern void v9fs_reclaim_fd(V9fsState *s);
 #endif
diff --git a/hw/an5206.c b/hw/an5206.c
index 04ca420a90..481ae60449 100644
--- a/hw/an5206.c
+++ b/hw/an5206.c
@@ -12,6 +12,7 @@
 #include "boards.h"
 #include "loader.h"
 #include "elf.h"
+#include "exec-memory.h"
 
 #define KERNEL_LOAD_ADDR 0x10000
 #define AN5206_MBAR_ADDR 0x10000000
@@ -37,6 +38,9 @@ static void an5206_init(ram_addr_t ram_size,
     int kernel_size;
     uint64_t elf_entry;
     target_phys_addr_t entry;
+    MemoryRegion *address_space_mem = get_system_memory();
+    MemoryRegion *ram = g_new(MemoryRegion, 1);
+    MemoryRegion *sram = g_new(MemoryRegion, 1);
 
     if (!cpu_model)
         cpu_model = "m5206";
@@ -52,12 +56,12 @@ static void an5206_init(ram_addr_t ram_size,
     env->rambar0 = AN5206_RAMBAR_ADDR | 1;
 
     /* DRAM at address zero */
-    cpu_register_physical_memory(0, ram_size,
-        qemu_ram_alloc(NULL, "an5206.ram", ram_size) | IO_MEM_RAM);
+    memory_region_init_ram(ram, NULL, "an5206.ram", ram_size);
+    memory_region_add_subregion(address_space_mem, 0, ram);
 
     /* Internal SRAM.  */
-    cpu_register_physical_memory(AN5206_RAMBAR_ADDR, 512,
-        qemu_ram_alloc(NULL, "an5206.sram", 512) | IO_MEM_RAM);
+    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);
 
diff --git a/hw/arm-misc.h b/hw/arm-misc.h
index f8a747289b..af403a159a 100644
--- a/hw/arm-misc.h
+++ b/hw/arm-misc.h
@@ -11,13 +11,16 @@
 #ifndef ARM_MISC_H
 #define ARM_MISC_H 1
 
+#include "memory.h"
+
 /* The CPU is also modeled as an interrupt controller.  */
 #define ARM_PIC_CPU_IRQ 0
 #define ARM_PIC_CPU_FIQ 1
 qemu_irq *arm_pic_init_cpu(CPUState *env);
 
 /* armv7m.c */
-qemu_irq *armv7m_init(int flash_size, int sram_size,
+qemu_irq *armv7m_init(MemoryRegion *address_space_mem,
+                      int flash_size, int sram_size,
                       const char *kernel_filename, const char *cpu_model);
 
 /* arm_boot.c */
diff --git a/hw/armv7m.c b/hw/armv7m.c
index a932f16a44..28d41b82a6 100644
--- a/hw/armv7m.c
+++ b/hw/armv7m.c
@@ -156,7 +156,8 @@ static void armv7m_reset(void *opaque)
    flash_size and sram_size are in kb.
    Returns the NVIC array.  */
 
-qemu_irq *armv7m_init(int flash_size, int sram_size,
+qemu_irq *armv7m_init(MemoryRegion *address_space_mem,
+                      int flash_size, int sram_size,
                       const char *kernel_filename, const char *cpu_model)
 {
     CPUState *env;
@@ -169,6 +170,9 @@ qemu_irq *armv7m_init(int flash_size, int sram_size,
     uint64_t lowaddr;
     int i;
     int big_endian;
+    MemoryRegion *sram = g_new(MemoryRegion, 1);
+    MemoryRegion *flash = g_new(MemoryRegion, 1);
+    MemoryRegion *hack = g_new(MemoryRegion, 1);
 
     flash_size *= 1024;
     sram_size *= 1024;
@@ -194,12 +198,11 @@ qemu_irq *armv7m_init(int flash_size, int sram_size,
 #endif
 
     /* Flash programming is done via the SCU, so pretend it is ROM.  */
-    cpu_register_physical_memory(0, flash_size,
-                                 qemu_ram_alloc(NULL, "armv7m.flash",
-                                                flash_size) | IO_MEM_ROM);
-    cpu_register_physical_memory(0x20000000, sram_size,
-                                 qemu_ram_alloc(NULL, "armv7m.sram",
-                                                sram_size) | IO_MEM_RAM);
+    memory_region_init_ram(flash, NULL, "armv7m.flash", flash_size);
+    memory_region_set_readonly(flash, true);
+    memory_region_add_subregion(address_space_mem, 0, flash);
+    memory_region_init_ram(sram, NULL, "armv7m.sram", sram_size);
+    memory_region_add_subregion(address_space_mem, 0x20000000, sram);
     armv7m_bitband_init();
 
     nvic = qdev_create(NULL, "armv7m_nvic");
@@ -232,9 +235,8 @@ qemu_irq *armv7m_init(int flash_size, int sram_size,
     /* Hack to map an additional page of ram at the top of the address
        space.  This stops qemu complaining about executing code outside RAM
        when returning from an exception.  */
-    cpu_register_physical_memory(0xfffff000, 0x1000,
-                                 qemu_ram_alloc(NULL, "armv7m.hack", 
-                                                0x1000) | IO_MEM_RAM);
+    memory_region_init_ram(hack, NULL, "armv7m.hack", 0x1000);
+    memory_region_add_subregion(address_space_mem, 0xfffff000, hack);
 
     qemu_register_reset(armv7m_reset, env);
     return pic;
diff --git a/hw/axis_dev88.c b/hw/axis_dev88.c
index 06200e257a..73eb39d43b 100644
--- a/hw/axis_dev88.c
+++ b/hw/axis_dev88.c
@@ -31,6 +31,7 @@
 #include "elf.h"
 #include "cris-boot.h"
 #include "blockdev.h"
+#include "exec-memory.h"
 
 #define D(x)
 #define DNAND(x)
@@ -259,8 +260,9 @@ void axisdev88_init (ram_addr_t ram_size,
     int i;
     int nand_regs;
     int gpio_regs;
-    ram_addr_t phys_ram;
-    ram_addr_t phys_intmem;
+    MemoryRegion *address_space_mem = get_system_memory();
+    MemoryRegion *phys_ram = g_new(MemoryRegion, 1);
+    MemoryRegion *phys_intmem = g_new(MemoryRegion, 1);
 
     /* init CPUs */
     if (cpu_model == NULL) {
@@ -269,15 +271,13 @@ void axisdev88_init (ram_addr_t ram_size,
     env = cpu_init(cpu_model);
 
     /* allocate RAM */
-    phys_ram = qemu_ram_alloc(NULL, "axisdev88.ram", ram_size);
-    cpu_register_physical_memory(0x40000000, ram_size, phys_ram | IO_MEM_RAM);
+    memory_region_init_ram(phys_ram, NULL, "axisdev88.ram", ram_size);
+    memory_region_add_subregion(address_space_mem, 0x40000000, phys_ram);
 
     /* The ETRAX-FS has 128Kb on chip ram, the docs refer to it as the 
        internal memory.  */
-    phys_intmem = qemu_ram_alloc(NULL, "axisdev88.chipram", INTMEM_SIZE);
-    cpu_register_physical_memory(0x38000000, INTMEM_SIZE,
-                                 phys_intmem | IO_MEM_RAM);
-
+    memory_region_init_ram(phys_intmem, NULL, "axisdev88.chipram", INTMEM_SIZE);
+    memory_region_add_subregion(address_space_mem, 0x38000000, phys_intmem);
 
       /* Attach a NAND flash to CS1.  */
     nand = drive_get(IF_MTD, 0, 0);
diff --git a/hw/cirrus_vga.c b/hw/cirrus_vga.c
index 4d0ef0d54c..ec7ea8207b 100644
--- a/hw/cirrus_vga.c
+++ b/hw/cirrus_vga.c
@@ -2424,6 +2424,7 @@ static void cirrus_update_memory_access(CirrusVGAState *s)
 {
     unsigned mode;
 
+    memory_region_transaction_begin();
     if ((s->vga.sr[0x17] & 0x44) == 0x44) {
         goto generic_io;
     } else if (s->cirrus_srcptr != s->cirrus_srcptr_end) {
@@ -2443,6 +2444,7 @@ static void cirrus_update_memory_access(CirrusVGAState *s)
             unmap_linear_vram(s);
         }
     }
+    memory_region_transaction_commit();
 }
 
 
diff --git a/hw/collie.c b/hw/collie.c
index 156404d9f3..a10cc1b90c 100644
--- a/hw/collie.c
+++ b/hw/collie.c
@@ -26,7 +26,6 @@ static void collie_init(ram_addr_t ram_size,
 {
     StrongARMState *s;
     DriveInfo *dinfo;
-    ram_addr_t phys_flash;
 
     if (!cpu_model) {
         cpu_model = "sa1110";
@@ -34,15 +33,13 @@ static void collie_init(ram_addr_t ram_size,
 
     s = sa1110_init(collie_binfo.ram_size, cpu_model);
 
-    phys_flash = qemu_ram_alloc(NULL, "collie.fl1", 0x02000000);
     dinfo = drive_get(IF_PFLASH, 0, 0);
-    pflash_cfi01_register(SA_CS0, phys_flash,
+    pflash_cfi01_register(SA_CS0, NULL, "collie.fl1", 0x02000000,
                     dinfo ? dinfo->bdrv : NULL, (64 * 1024),
                     512, 4, 0x00, 0x00, 0x00, 0x00, 0);
 
-    phys_flash = qemu_ram_alloc(NULL, "collie.fl2", 0x02000000);
     dinfo = drive_get(IF_PFLASH, 0, 1);
-    pflash_cfi01_register(SA_CS1, phys_flash,
+    pflash_cfi01_register(SA_CS1, NULL, "collie.fl2", 0x02000000,
                     dinfo ? dinfo->bdrv : NULL, (64 * 1024),
                     512, 4, 0x00, 0x00, 0x00, 0x00, 0);
 
diff --git a/hw/dec_pci.c b/hw/dec_pci.c
index a35f382052..1aec06611c 100644
--- a/hw/dec_pci.c
+++ b/hw/dec_pci.c
@@ -80,16 +80,15 @@ PCIBus *pci_dec_21154_init(PCIBus *parent_bus, int devfn)
 static int pci_dec_21154_init_device(SysBusDevice *dev)
 {
     DECState *s;
-    int pci_mem_config, pci_mem_data;
 
     s = FROM_SYSBUS(DECState, dev);
 
-    pci_mem_config = pci_host_conf_register_mmio(&s->host_state,
-                                                 DEVICE_LITTLE_ENDIAN);
-    pci_mem_data = pci_host_data_register_mmio(&s->host_state,
-                                               DEVICE_LITTLE_ENDIAN);
-    sysbus_init_mmio(dev, 0x1000, pci_mem_config);
-    sysbus_init_mmio(dev, 0x1000, pci_mem_data);
+    memory_region_init_io(&s->host_state.conf_mem, &pci_host_conf_le_ops,
+                          &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);
     return 0;
 }
 
diff --git a/hw/dummy_m68k.c b/hw/dummy_m68k.c
index eed9e3843c..30146b9c9d 100644
--- a/hw/dummy_m68k.c
+++ b/hw/dummy_m68k.c
@@ -10,6 +10,7 @@
 #include "boards.h"
 #include "loader.h"
 #include "elf.h"
+#include "exec-memory.h"
 
 #define KERNEL_LOAD_ADDR 0x10000
 
@@ -21,6 +22,8 @@ static void dummy_m68k_init(ram_addr_t ram_size,
                      const char *initrd_filename, const char *cpu_model)
 {
     CPUState *env;
+    MemoryRegion *address_space_mem =  get_system_memory();
+    MemoryRegion *ram = g_new(MemoryRegion, 1);
     int kernel_size;
     uint64_t elf_entry;
     target_phys_addr_t entry;
@@ -37,8 +40,8 @@ static void dummy_m68k_init(ram_addr_t ram_size,
     env->vbr = 0;
 
     /* RAM at address zero */
-    cpu_register_physical_memory(0, ram_size,
-        qemu_ram_alloc(NULL, "dummy_m68k.ram", ram_size) | IO_MEM_RAM);
+    memory_region_init_ram(ram, NULL, "dummy_m68k.ram", ram_size);
+    memory_region_add_subregion(address_space_mem, 0, ram);
 
     /* Load kernel.  */
     if (kernel_filename) {
diff --git a/hw/fdc.c b/hw/fdc.c
index 580b657791..1d44bbd1e3 100644
--- a/hw/fdc.c
+++ b/hw/fdc.c
@@ -535,30 +535,11 @@ static CPUWriteMemoryFunc * const fdctrl_mem_write_strict[3] = {
     NULL,
 };
 
-static void fdrive_media_changed_pre_save(void *opaque)
-{
-    FDrive *drive = opaque;
-
-    drive->media_changed = drive->bs->media_changed;
-}
-
-static int fdrive_media_changed_post_load(void *opaque, int version_id)
-{
-    FDrive *drive = opaque;
-
-    if (drive->bs != NULL) {
-        drive->bs->media_changed = drive->media_changed;
-    }
-
-    /* User ejected the floppy when drive->bs == NULL */
-    return 0;
-}
-
 static bool fdrive_media_changed_needed(void *opaque)
 {
     FDrive *drive = opaque;
 
-    return (drive->bs != NULL && drive->bs->media_changed != 1);
+    return (drive->bs != NULL && drive->media_changed != 1);
 }
 
 static const VMStateDescription vmstate_fdrive_media_changed = {
@@ -566,8 +547,6 @@ static const VMStateDescription vmstate_fdrive_media_changed = {
     .version_id = 1,
     .minimum_version_id = 1,
     .minimum_version_id_old = 1,
-    .pre_save = fdrive_media_changed_pre_save,
-    .post_load = fdrive_media_changed_post_load,
     .fields      = (VMStateField[]) {
         VMSTATE_UINT8(media_changed, FDrive),
         VMSTATE_END_OF_LIST()
@@ -919,7 +898,15 @@ static int fdctrl_media_changed(FDrive *drv)
 
     if (!drv->bs)
         return 0;
-    ret = bdrv_media_changed(drv->bs);
+    if (drv->media_changed) {
+        drv->media_changed = 0;
+        ret = 1;
+    } else {
+        ret = bdrv_media_changed(drv->bs);
+        if (ret < 0) {
+            ret = 0;            /* we don't know, assume no */
+        }
+    }
     if (ret) {
         fd_revalidate(drv);
     }
@@ -1791,6 +1778,17 @@ static void fdctrl_result_timer(void *opaque)
     fdctrl_stop_transfer(fdctrl, 0x00, 0x00, 0x00);
 }
 
+static void fdctrl_change_cb(void *opaque)
+{
+    FDrive *drive = opaque;
+
+    drive->media_changed = 1;
+}
+
+static const BlockDevOps fdctrl_block_ops = {
+    .change_media_cb = fdctrl_change_cb,
+};
+
 /* Init functions */
 static int fdctrl_connect_drives(FDCtrl *fdctrl)
 {
@@ -1814,7 +1812,9 @@ static int fdctrl_connect_drives(FDCtrl *fdctrl)
         fd_init(drive);
         fd_revalidate(drive);
         if (drive->bs) {
+            drive->media_changed = 1;
             bdrv_set_removable(drive->bs, 1);
+            bdrv_set_dev_ops(drive->bs, &fdctrl_block_ops, drive);
         }
     }
     return 0;
diff --git a/hw/flash.h b/hw/flash.h
index 270be5e127..9c9e5265b7 100644
--- a/hw/flash.h
+++ b/hw/flash.h
@@ -1,15 +1,22 @@
 /* NOR flash devices */
+
+#include "memory.h"
+
 typedef struct pflash_t pflash_t;
 
 /* pflash_cfi01.c */
-pflash_t *pflash_cfi01_register(target_phys_addr_t base, ram_addr_t off,
+pflash_t *pflash_cfi01_register(target_phys_addr_t base,
+                                DeviceState *qdev, const char *name,
+                                target_phys_addr_t size,
                                 BlockDriverState *bs,
                                 uint32_t sector_len, int nb_blocs, int width,
                                 uint16_t id0, uint16_t id1,
                                 uint16_t id2, uint16_t id3, int be);
 
 /* pflash_cfi02.c */
-pflash_t *pflash_cfi02_register(target_phys_addr_t base, ram_addr_t off,
+pflash_t *pflash_cfi02_register(target_phys_addr_t base,
+                                DeviceState *qdev, const char *name,
+                                target_phys_addr_t size,
                                 BlockDriverState *bs, uint32_t sector_len,
                                 int nb_blocs, int nb_mappings, int width,
                                 uint16_t id0, uint16_t id1,
@@ -17,6 +24,8 @@ pflash_t *pflash_cfi02_register(target_phys_addr_t base, ram_addr_t off,
                                 uint16_t unlock_addr0, uint16_t unlock_addr1,
                                 int be);
 
+MemoryRegion *pflash_cfi01_get_memory(pflash_t *fl);
+
 /* nand.c */
 DeviceState *nand_init(BlockDriverState *bdrv, int manf_id, int chip_id);
 void nand_setpins(DeviceState *dev, uint8_t cle, uint8_t ale,
diff --git a/hw/grackle_pci.c b/hw/grackle_pci.c
index 9a823e1c06..9d3ff7d555 100644
--- a/hw/grackle_pci.c
+++ b/hw/grackle_pci.c
@@ -92,16 +92,15 @@ PCIBus *pci_grackle_init(uint32_t base, qemu_irq *pic,
 static int pci_grackle_init_device(SysBusDevice *dev)
 {
     GrackleState *s;
-    int pci_mem_config, pci_mem_data;
 
     s = FROM_SYSBUS(GrackleState, dev);
 
-    pci_mem_config = pci_host_conf_register_mmio(&s->host_state,
-                                                 DEVICE_LITTLE_ENDIAN);
-    pci_mem_data = pci_host_data_register_mmio(&s->host_state,
-                                               DEVICE_LITTLE_ENDIAN);
-    sysbus_init_mmio(dev, 0x1000, pci_mem_config);
-    sysbus_init_mmio(dev, 0x1000, pci_mem_data);
+    memory_region_init_io(&s->host_state.conf_mem, &pci_host_conf_le_ops,
+                          &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);
 
     qemu_register_reset(pci_grackle_reset, &s->host_state);
     return 0;
diff --git a/hw/gumstix.c b/hw/gumstix.c
index 853f7e1ee8..b8b76f4b87 100644
--- a/hw/gumstix.c
+++ b/hw/gumstix.c
@@ -67,8 +67,7 @@ static void connex_init(ram_addr_t ram_size,
 #else
     be = 0;
 #endif
-    if (!pflash_cfi01_register(0x00000000, qemu_ram_alloc(NULL, "connext.rom",
-                                                          connex_rom),
+    if (!pflash_cfi01_register(0x00000000, NULL, "connext.rom", connex_rom,
                                dinfo->bdrv, sector_len, connex_rom / sector_len,
                                2, 0, 0, 0, 0, be)) {
         fprintf(stderr, "qemu: Error registering flash memory.\n");
@@ -106,8 +105,7 @@ static void verdex_init(ram_addr_t ram_size,
 #else
     be = 0;
 #endif
-    if (!pflash_cfi01_register(0x00000000, qemu_ram_alloc(NULL, "verdex.rom",
-                                                          verdex_rom),
+    if (!pflash_cfi01_register(0x00000000, NULL, "verdex.rom", verdex_rom,
                                dinfo->bdrv, sector_len, verdex_rom / sector_len,
                                2, 0, 0, 0, 0, be)) {
         fprintf(stderr, "qemu: Error registering flash memory.\n");
diff --git a/hw/ide/core.c b/hw/ide/core.c
index 40abc1edd2..1806e008bc 100644
--- a/hw/ide/core.c
+++ b/hw/ide/core.c
@@ -783,15 +783,11 @@ static void ide_cfata_metadata_write(IDEState *s)
 }
 
 /* called when the inserted state of the media has changed */
-static void cdrom_change_cb(void *opaque, int reason)
+static void ide_cd_change_cb(void *opaque)
 {
     IDEState *s = opaque;
     uint64_t nb_sectors;
 
-    if (!(reason & CHANGE_MEDIA)) {
-        return;
-    }
-
     bdrv_get_geometry(s->bs, &nb_sectors);
     s->nb_sectors = nb_sectors;
 
@@ -983,7 +979,7 @@ void ide_exec_cmd(IDEBus *bus, uint32_t val)
         s->status = READY_STAT | SEEK_STAT;
         ide_set_irq(s->bus);
         break;
-	case WIN_READ_EXT:
+    case WIN_READ_EXT:
 	lba48 = 1;
     case WIN_READ:
     case WIN_READ_ONCE:
@@ -993,7 +989,7 @@ void ide_exec_cmd(IDEBus *bus, uint32_t val)
         s->req_nb_sectors = 1;
         ide_sector_read(s);
         break;
-	case WIN_WRITE_EXT:
+    case WIN_WRITE_EXT:
 	lba48 = 1;
     case WIN_WRITE:
     case WIN_WRITE_ONCE:
@@ -1006,7 +1002,7 @@ void ide_exec_cmd(IDEBus *bus, uint32_t val)
         ide_transfer_start(s, s->io_buffer, 512, ide_sector_write);
         s->media_changed = 1;
         break;
-	case WIN_MULTREAD_EXT:
+    case WIN_MULTREAD_EXT:
 	lba48 = 1;
     case WIN_MULTREAD:
         if (!s->mult_sectors)
@@ -1031,7 +1027,7 @@ void ide_exec_cmd(IDEBus *bus, uint32_t val)
         ide_transfer_start(s, s->io_buffer, 512 * n, ide_sector_write);
         s->media_changed = 1;
         break;
-	case WIN_READDMA_EXT:
+    case WIN_READDMA_EXT:
 	lba48 = 1;
     case WIN_READDMA:
     case WIN_READDMA_ONCE:
@@ -1040,7 +1036,7 @@ void ide_exec_cmd(IDEBus *bus, uint32_t val)
 	ide_cmd_lba48_transform(s, lba48);
         ide_sector_start_dma(s, IDE_DMA_READ);
         break;
-	case WIN_WRITEDMA_EXT:
+    case WIN_WRITEDMA_EXT:
 	lba48 = 1;
     case WIN_WRITEDMA:
     case WIN_WRITEDMA_ONCE:
@@ -1133,7 +1129,7 @@ void ide_exec_cmd(IDEBus *bus, uint32_t val)
     case WIN_STANDBYNOW1:
     case WIN_STANDBYNOW2:
     case WIN_IDLEIMMEDIATE:
-    case CFA_IDLEIMMEDIATE:
+    case WIN_IDLEIMMEDIATE2:
     case WIN_SETIDLE1:
     case WIN_SETIDLE2:
     case WIN_SLEEPNOW1:
@@ -1172,7 +1168,7 @@ void ide_exec_cmd(IDEBus *bus, uint32_t val)
                           */
         ide_set_irq(s->bus);
         break;
-    case WIN_SRST:
+    case WIN_DEVICE_RESET:
         if (s->drive_kind != IDE_CD)
             goto abort_cmd;
         ide_set_signature(s);
@@ -1265,7 +1261,7 @@ void ide_exec_cmd(IDEBus *bus, uint32_t val)
         ide_set_irq(s->bus);
         break;
 
-	case WIN_SMART:
+    case WIN_SMART:
 	if (s->drive_kind == IDE_CD)
 		goto abort_cmd;
 	if (s->hcyl != 0xc2 || s->lcyl != 0x4f)
@@ -1742,6 +1738,10 @@ void ide_bus_reset(IDEBus *bus)
     bus->dma->ops->reset(bus->dma);
 }
 
+static const BlockDevOps ide_cd_block_ops = {
+    .change_media_cb = ide_cd_change_cb,
+};
+
 int ide_init_drive(IDEState *s, BlockDriverState *bs, IDEDriveKind kind,
                    const char *version, const char *serial)
 {
@@ -1776,7 +1776,7 @@ int ide_init_drive(IDEState *s, BlockDriverState *bs, IDEDriveKind kind,
     s->smart_errors = 0;
     s->smart_selftest_count = 0;
     if (kind == IDE_CD) {
-        bdrv_set_change_cb(bs, cdrom_change_cb, s);
+        bdrv_set_dev_ops(bs, &ide_cd_block_ops, s);
         bs->buffer_alignment = 2048;
     } else {
         if (!bdrv_is_inserted(s->bs)) {
@@ -1890,6 +1890,7 @@ void ide_init2_with_non_qdev_drives(IDEBus *bus, DriveInfo *hd0,
                 error_report("Can't set up IDE drive %s", dinfo->id);
                 exit(1);
             }
+            bdrv_attach_dev_nofail(dinfo->bdrv, &bus->ifs[i]);
         } else {
             ide_reset(&bus->ifs[i]);
         }
@@ -2009,7 +2010,7 @@ static bool ide_error_needed(void *opaque)
 }
 
 /* Fields for GET_EVENT_STATUS_NOTIFICATION ATAPI command */
-const VMStateDescription vmstate_ide_atapi_gesn_state = {
+static const VMStateDescription vmstate_ide_atapi_gesn_state = {
     .name ="ide_drive/atapi/gesn_state",
     .version_id = 1,
     .minimum_version_id = 1,
@@ -2021,7 +2022,7 @@ const VMStateDescription vmstate_ide_atapi_gesn_state = {
     }
 };
 
-const VMStateDescription vmstate_ide_drive_pio_state = {
+static const VMStateDescription vmstate_ide_drive_pio_state = {
     .name = "ide_drive/pio_state",
     .version_id = 1,
     .minimum_version_id = 1,
@@ -2083,7 +2084,7 @@ const VMStateDescription vmstate_ide_drive = {
     }
 };
 
-const VMStateDescription vmstate_ide_error_status = {
+static const VMStateDescription vmstate_ide_error_status = {
     .name ="ide_bus/error",
     .version_id = 1,
     .minimum_version_id = 1,
diff --git a/hw/ide/internal.h b/hw/ide/internal.h
index 7f5ef8de1d..111785294d 100644
--- a/hw/ide/internal.h
+++ b/hw/ide/internal.h
@@ -55,111 +55,120 @@ typedef struct IDEDMAOps IDEDMAOps;
 #define IDE_CMD_RESET           0x04
 #define IDE_CMD_DISABLE_IRQ     0x02
 
-/* ATA/ATAPI Commands pre T13 Spec */
+/* ACS-2 T13/2015-D Table B.2 Command codes */
 #define WIN_NOP				0x00
-/*
- *	0x01->0x02 Reserved
- */
+/* reserved                             0x01..0x02 */
 #define CFA_REQ_EXT_ERROR_CODE		0x03 /* CFA Request Extended Error Code */
-/*
- *      0x04->0x05 Reserved
- */
+/* reserved                             0x04..0x05 */
 #define WIN_DSM                         0x06
-/*
- *      0x07 Reserved
- */
-#define WIN_SRST			0x08 /* ATAPI soft reset command */
+/* reserved                             0x07 */
 #define WIN_DEVICE_RESET		0x08
-/*
- *	0x09->0x0F Reserved
- */
-#define WIN_RECAL			0x10
-#define WIN_RESTORE			WIN_RECAL
-/*
- *	0x10->0x1F Reserved
- */
+/* reserved                             0x09..0x0a */
+/* REQUEST SENSE DATA EXT               0x0B */
+/* reserved                             0x0C..0x0F */
+#define WIN_RECAL                       0x10 /* obsolete since ATA4 */
+/* obsolete since ATA3, retired in ATA4 0x11..0x1F */
 #define WIN_READ			0x20 /* 28-Bit */
-#define WIN_READ_ONCE			0x21 /* 28-Bit without retries */
-#define WIN_READ_LONG			0x22 /* 28-Bit */
-#define WIN_READ_LONG_ONCE		0x23 /* 28-Bit without retries */
+#define WIN_READ_ONCE                   0x21 /* 28-Bit w/o retries, obsolete since ATA5 */
+/* obsolete since ATA4                  0x22..0x23 */
 #define WIN_READ_EXT			0x24 /* 48-Bit */
 #define WIN_READDMA_EXT			0x25 /* 48-Bit */
-#define WIN_READDMA_QUEUED_EXT		0x26 /* 48-Bit */
+#define WIN_READDMA_QUEUED_EXT          0x26 /* 48-Bit, obsolete since ACS2 */
 #define WIN_READ_NATIVE_MAX_EXT		0x27 /* 48-Bit */
-/*
- *	0x28
- */
+/* reserved                             0x28 */
 #define WIN_MULTREAD_EXT		0x29 /* 48-Bit */
-/*
- *	0x2A->0x2F Reserved
- */
+/* READ STREAM DMA EXT                  0x2A */
+/* READ STREAM EXT                      0x2B */
+/* reserved                             0x2C..0x2E */
+/* READ LOG EXT                         0x2F */
 #define WIN_WRITE			0x30 /* 28-Bit */
-#define WIN_WRITE_ONCE			0x31 /* 28-Bit without retries */
-#define WIN_WRITE_LONG			0x32 /* 28-Bit */
-#define WIN_WRITE_LONG_ONCE		0x33 /* 28-Bit without retries */
+#define WIN_WRITE_ONCE                  0x31 /* 28-Bit w/o retries, obsolete since ATA5 */
+/* obsolete since ATA4                  0x32..0x33 */
 #define WIN_WRITE_EXT			0x34 /* 48-Bit */
 #define WIN_WRITEDMA_EXT		0x35 /* 48-Bit */
 #define WIN_WRITEDMA_QUEUED_EXT		0x36 /* 48-Bit */
+#define WIN_SET_MAX_EXT                 0x37 /* 48-Bit, obsolete since ACS2 */
 #define WIN_SET_MAX_EXT			0x37 /* 48-Bit */
 #define CFA_WRITE_SECT_WO_ERASE		0x38 /* CFA Write Sectors without erase */
 #define WIN_MULTWRITE_EXT		0x39 /* 48-Bit */
-/*
- *	0x3A->0x3B Reserved
- */
-#define WIN_WRITE_VERIFY		0x3C /* 28-Bit */
-/*
- *	0x3D->0x3F Reserved
- */
+/* WRITE STREAM DMA EXT                 0x3A */
+/* WRITE STREAM EXT                     0x3B */
+#define WIN_WRITE_VERIFY                0x3C /* 28-Bit, obsolete since ATA4 */
+/* WRITE DMA FUA EXT                    0x3D */
+/* obsolete since ACS2                  0x3E */
+/* WRITE LOG EXT                        0x3F */
 #define WIN_VERIFY			0x40 /* 28-Bit - Read Verify Sectors */
-#define WIN_VERIFY_ONCE			0x41 /* 28-Bit - without retries */
+#define WIN_VERIFY_ONCE                 0x41 /* 28-Bit - w/o retries, obsolete since ATA5 */
 #define WIN_VERIFY_EXT			0x42 /* 48-Bit */
-/*
- *	0x43->0x4F Reserved
- */
-#define WIN_FORMAT			0x50
-/*
- *	0x51->0x5F Reserved
- */
-#define WIN_INIT			0x60
-/*
- *	0x61->0x5F Reserved
- */
-#define WIN_SEEK			0x70 /* 0x70-0x7F Reserved */
+/* reserved                             0x43..0x44 */
+/* WRITE UNCORRECTABLE EXT              0x45 */
+/* reserved                             0x46 */
+/* READ LOG DMA EXT                     0x47 */
+/* reserved                             0x48..0x4F */
+/* obsolete since ATA4                  0x50 */
+/* CONFIGURE STREAM                     0x51 */
+/* reserved                             0x52..0x56 */
+/* WRITE LOG DMA EXT                    0x57 */
+/* reserved                             0x58..0x5A */
+/* TRUSTED NON DATA                     0x5B */
+/* TRUSTED RECEIVE                      0x5C */
+/* TRUSTED RECEIVE DMA                  0x5D */
+/* TRUSTED SEND                         0x5E */
+/* TRUSTED SEND DMA                     0x5F */
+/* READ FPDMA QUEUED                    0x60 */
+/* WRITE FPDMA QUEUED                   0x61 */
+/* reserved                             0x62->0x6F */
+#define WIN_SEEK                        0x70 /* obsolete since ATA7 */
+/* reserved                             0x71-0x7F */
+/* vendor specific                      0x80-0x86 */
 #define CFA_TRANSLATE_SECTOR		0x87 /* CFA Translate Sector */
+/* vendor specific                      0x88-0x8F */
 #define WIN_DIAGNOSE			0x90
-#define WIN_SPECIFY			0x91 /* set drive geometry translation */
+#define WIN_SPECIFY                     0x91 /* set drive geometry translation, obsolete since ATA6 */
 #define WIN_DOWNLOAD_MICROCODE		0x92
-#define WIN_STANDBYNOW2			0x94
-#define CFA_IDLEIMMEDIATE		0x95 /* force drive to become "ready" */
-#define WIN_STANDBY2			0x96
-#define WIN_SETIDLE2			0x97
-#define WIN_CHECKPOWERMODE2		0x98
-#define WIN_SLEEPNOW2			0x99
-/*
- *	0x9A VENDOR
- */
+/* DOWNLOAD MICROCODE DMA               0x93 */
+#define WIN_STANDBYNOW2                 0x94 /* retired in ATA4 */
+#define WIN_IDLEIMMEDIATE2              0x95 /* force drive to become "ready", retired in ATA4 */
+#define WIN_STANDBY2                    0x96 /* retired in ATA4 */
+#define WIN_SETIDLE2                    0x97 /* retired in ATA4 */
+#define WIN_CHECKPOWERMODE2             0x98 /* retired in ATA4 */
+#define WIN_SLEEPNOW2                   0x99 /* retired in ATA4 */
+/* vendor specific                      0x9A */
+/* reserved                             0x9B..0x9F */
 #define WIN_PACKETCMD			0xA0 /* Send a packet command. */
 #define WIN_PIDENTIFY			0xA1 /* identify ATAPI device	*/
-#define WIN_QUEUED_SERVICE		0xA2
+#define WIN_QUEUED_SERVICE              0xA2 /* obsolete since ACS2 */
+/* reserved                             0xA3..0xAF */
 #define WIN_SMART			0xB0 /* self-monitoring and reporting */
+/* Device Configuration Overlay         0xB1 */
+/* reserved                             0xB2..0xB3 */
+/* Sanitize Device                      0xB4 */
+/* reserved                             0xB5 */
+/* NV Cache                             0xB6 */
+/* reserved for CFA                     0xB7..0xBB */
 #define CFA_ACCESS_METADATA_STORAGE	0xB8
+/* reserved                             0xBC..0xBF */
 #define CFA_ERASE_SECTORS       	0xC0 /* microdrives implement as NOP */
+/* vendor specific                      0xC1..0xC3 */
 #define WIN_MULTREAD			0xC4 /* read sectors using multiple mode*/
 #define WIN_MULTWRITE			0xC5 /* write sectors using multiple mode */
 #define WIN_SETMULT			0xC6 /* enable/disable multiple mode */
-#define WIN_READDMA_QUEUED		0xC7 /* read sectors using Queued DMA transfers */
+#define WIN_READDMA_QUEUED              0xC7 /* read sectors using Queued DMA transfers, obsolete since ACS2 */
 #define WIN_READDMA			0xC8 /* read sectors using DMA transfers */
-#define WIN_READDMA_ONCE		0xC9 /* 28-Bit - without retries */
+#define WIN_READDMA_ONCE                0xC9 /* 28-Bit - w/o retries, obsolete since ATA5 */
 #define WIN_WRITEDMA			0xCA /* write sectors using DMA transfers */
-#define WIN_WRITEDMA_ONCE		0xCB /* 28-Bit - without retries */
-#define WIN_WRITEDMA_QUEUED		0xCC /* write sectors using Queued DMA transfers */
+#define WIN_WRITEDMA_ONCE               0xCB /* 28-Bit - w/o retries, obsolete since ATA5 */
+#define WIN_WRITEDMA_QUEUED		0xCC /* write sectors using Queued DMA transfers, obsolete since ACS2 */
 #define CFA_WRITE_MULTI_WO_ERASE	0xCD /* CFA Write multiple without erase */
-#define WIN_GETMEDIASTATUS		0xDA
-#define WIN_ACKMEDIACHANGE		0xDB /* ATA-1, ATA-2 vendor */
-#define WIN_POSTBOOT			0xDC
-#define WIN_PREBOOT			0xDD
-#define WIN_DOORLOCK			0xDE /* lock door on removable drives */
-#define WIN_DOORUNLOCK			0xDF /* unlock door on removable drives */
+/* WRITE MULTIPLE FUA EXT               0xCE */
+/* reserved                             0xCF..0xDO */
+/* CHECK MEDIA CARD TYPE                0xD1 */
+/* reserved for media card pass through 0xD2..0xD4 */
+/* reserved                             0xD5..0xD9 */
+#define WIN_GETMEDIASTATUS              0xDA /* obsolete since ATA8 */
+/* obsolete since ATA3, retired in ATA4 0xDB..0xDD */
+#define WIN_DOORLOCK                    0xDE /* lock door on removable drives, obsolete since ATA8 */
+#define WIN_DOORUNLOCK                  0xDF /* unlock door on removable drives, obsolete since ATA8 */
 #define WIN_STANDBYNOW1			0xE0
 #define WIN_IDLEIMMEDIATE		0xE1 /* force drive to become "ready" */
 #define WIN_STANDBY             	0xE2 /* Set device in Standby Mode */
@@ -169,25 +178,25 @@ typedef struct IDEDMAOps IDEDMAOps;
 #define WIN_SLEEPNOW1			0xE6
 #define WIN_FLUSH_CACHE			0xE7
 #define WIN_WRITE_BUFFER		0xE8 /* force write only 1 sector */
-#define WIN_WRITE_SAME			0xE9 /* read ata-2 to use */
-	/* SET_FEATURES 0x22 or 0xDD */
+/* READ BUFFER DMA                      0xE9 */
 #define WIN_FLUSH_CACHE_EXT		0xEA /* 48-Bit */
+/* WRITE BUFFER DMA                     0xEB */
 #define WIN_IDENTIFY			0xEC /* ask drive to identify itself	*/
-#define WIN_MEDIAEJECT			0xED
-#define WIN_IDENTIFY_DMA		0xEE /* same as WIN_IDENTIFY, but DMA */
+#define WIN_MEDIAEJECT                  0xED /* obsolete since ATA8 */
+/* obsolete since ATA4                  0xEE */
 #define WIN_SETFEATURES			0xEF /* set special drive features */
-#define EXABYTE_ENABLE_NEST		0xF0
-#define IBM_SENSE_CONDITION		0xF0 /* measure disk temperature */
+#define IBM_SENSE_CONDITION             0xF0 /* measure disk temperature, vendor specific */
 #define WIN_SECURITY_SET_PASS		0xF1
 #define WIN_SECURITY_UNLOCK		0xF2
 #define WIN_SECURITY_ERASE_PREPARE	0xF3
 #define WIN_SECURITY_ERASE_UNIT		0xF4
 #define WIN_SECURITY_FREEZE_LOCK	0xF5
-#define CFA_WEAR_LEVEL			0xF5 /* microdrives implement as NOP */
+#define CFA_WEAR_LEVEL                  0xF5 /* microdrives implement as NOP; not specified in T13! */
 #define WIN_SECURITY_DISABLE		0xF6
+/* vendor specific                      0xF7 */
 #define WIN_READ_NATIVE_MAX		0xF8 /* return the native maximum address */
 #define WIN_SET_MAX			0xF9
-#define DISABLE_SEAGATE			0xFB
+/* vendor specific                      0xFA..0xFF */
 
 /* set to 1 set disable mult support */
 #define MAX_MULT_SECTORS 16
diff --git a/hw/ide/piix.c b/hw/ide/piix.c
index 8525336075..88d318127c 100644
--- a/hw/ide/piix.c
+++ b/hw/ide/piix.c
@@ -27,7 +27,6 @@
 #include <hw/pci.h>
 #include <hw/isa.h>
 #include "block.h"
-#include "block_int.h"
 #include "sysemu.h"
 #include "dma.h"
 
@@ -176,10 +175,10 @@ static int pci_piix3_xen_ide_unplug(DeviceState *dev)
 
     for (; i < 3; i++) {
         di = drive_get_by_index(IF_IDE, i);
-        if (di != NULL && di->bdrv != NULL && !di->bdrv->removable) {
-            DeviceState *ds = bdrv_get_attached(di->bdrv);
+        if (di != NULL && !di->media_cd) {
+            DeviceState *ds = bdrv_get_attached_dev(di->bdrv);
             if (ds) {
-                bdrv_detach(di->bdrv, ds);
+                bdrv_detach_dev(di->bdrv, ds);
             }
             bdrv_close(di->bdrv);
             pci_ide->bus[di->bus].ifs[di->unit].bs = NULL;
diff --git a/hw/integratorcp.c b/hw/integratorcp.c
index 281410899f..3c8982ea29 100644
--- a/hw/integratorcp.c
+++ b/hw/integratorcp.c
@@ -13,11 +13,13 @@
 #include "boards.h"
 #include "arm-misc.h"
 #include "net.h"
+#include "exec-memory.h"
 
 typedef struct {
     SysBusDevice busdev;
     uint32_t memsz;
-    uint32_t flash_offset;
+    MemoryRegion flash;
+    bool flash_mapped;
     uint32_t cm_osc;
     uint32_t cm_ctrl;
     uint32_t cm_lock;
@@ -108,9 +110,15 @@ static uint32_t integratorcm_read(void *opaque, target_phys_addr_t offset)
 static void integratorcm_do_remap(integratorcm_state *s, int flash)
 {
     if (flash) {
-        cpu_register_physical_memory(0, 0x100000, IO_MEM_RAM);
+        if (s->flash_mapped) {
+            sysbus_del_memory(&s->busdev, &s->flash);
+            s->flash_mapped = false;
+        }
     } else {
-        cpu_register_physical_memory(0, 0x100000, s->flash_offset | IO_MEM_RAM);
+        if (!s->flash_mapped) {
+            sysbus_add_memory_overlap(&s->busdev, 0, &s->flash, 1);
+            s->flash_mapped = true;
+        }
     }
     //??? tlb_flush (cpu_single_env, 1);
 }
@@ -252,7 +260,8 @@ static int integratorcm_init(SysBusDevice *dev)
     }
     memcpy(integrator_spd + 73, "QEMU-MEMORY", 11);
     s->cm_init = 0x00000112;
-    s->flash_offset = qemu_ram_alloc(NULL, "integrator.flash", 0x100000);
+    memory_region_init_ram(&s->flash, NULL, "integrator.flash", 0x100000);
+    s->flash_mapped = false;
 
     iomemtype = cpu_register_io_memory(integratorcm_readfn,
                                        integratorcm_writefn, s,
@@ -456,7 +465,9 @@ static void integratorcp_init(ram_addr_t ram_size,
                      const char *initrd_filename, const char *cpu_model)
 {
     CPUState *env;
-    ram_addr_t ram_offset;
+    MemoryRegion *address_space_mem = get_system_memory();
+    MemoryRegion *ram = g_new(MemoryRegion, 1);
+    MemoryRegion *ram_alias = g_new(MemoryRegion, 1);
     qemu_irq pic[32];
     qemu_irq *cpu_pic;
     DeviceState *dev;
@@ -469,13 +480,14 @@ static void integratorcp_init(ram_addr_t ram_size,
         fprintf(stderr, "Unable to find CPU definition\n");
         exit(1);
     }
-    ram_offset = qemu_ram_alloc(NULL, "integrator.ram", ram_size);
+    memory_region_init_ram(ram, NULL, "integrator.ram", ram_size);
     /* ??? On a real system the first 1Mb is mapped as SSRAM or boot flash.  */
     /* ??? RAM should repeat to fill physical memory space.  */
     /* SDRAM at address zero*/
-    cpu_register_physical_memory(0, ram_size, ram_offset | IO_MEM_RAM);
+    memory_region_add_subregion(address_space_mem, 0, ram);
     /* And again at address 0x80000000 */
-    cpu_register_physical_memory(0x80000000, ram_size, ram_offset | IO_MEM_RAM);
+    memory_region_init_alias(ram_alias, "ram.alias", ram, 0, ram_size);
+    memory_region_add_subregion(address_space_mem, 0x80000000, ram_alias);
 
     dev = qdev_create(NULL, "integrator_core");
     qdev_prop_set_uint32(dev, "memsz", ram_size >> 20);
diff --git a/hw/leon3.c b/hw/leon3.c
index a62a9419f3..607ec852fe 100644
--- a/hw/leon3.c
+++ b/hw/leon3.c
@@ -29,6 +29,7 @@
 #include "loader.h"
 #include "elf.h"
 #include "trace.h"
+#include "exec-memory.h"
 
 #include "grlib.h"
 
@@ -100,7 +101,9 @@ static void leon3_generic_hw_init(ram_addr_t  ram_size,
                                   const char *cpu_model)
 {
     CPUState   *env;
-    ram_addr_t  ram_offset, prom_offset;
+    MemoryRegion *address_space_mem = get_system_memory();
+    MemoryRegion *ram = g_new(MemoryRegion, 1);
+    MemoryRegion *prom = g_new(MemoryRegion, 1);
     int         ret;
     char       *filename;
     qemu_irq   *cpu_irqs = NULL;
@@ -139,14 +142,14 @@ static void leon3_generic_hw_init(ram_addr_t  ram_size,
         exit(1);
     }
 
-    ram_offset = qemu_ram_alloc(NULL, "leon3.ram", ram_size);
-    cpu_register_physical_memory(0x40000000, ram_size, ram_offset | IO_MEM_RAM);
+    memory_region_init_ram(ram, NULL, "leon3.ram", ram_size);
+    memory_region_add_subregion(address_space_mem, 0x40000000, ram);
 
     /* Allocate BIOS */
     prom_size = 8 * 1024 * 1024; /* 8Mb */
-    prom_offset = qemu_ram_alloc(NULL, "Leon3.bios", prom_size);
-    cpu_register_physical_memory(0x00000000, prom_size,
-                                 prom_offset | IO_MEM_ROM);
+    memory_region_init_ram(prom, NULL, "Leon3.bios", prom_size);
+    memory_region_set_readonly(prom, true);
+    memory_region_add_subregion(address_space_mem, 0x00000000, prom);
 
     /* Load boot prom */
     if (bios_name == NULL) {
diff --git a/hw/lm32_boards.c b/hw/lm32_boards.c
index d18aad7435..97e1c001b9 100644
--- a/hw/lm32_boards.c
+++ b/hw/lm32_boards.c
@@ -28,6 +28,7 @@
 #include "elf.h"
 #include "lm32_hwsetup.h"
 #include "lm32.h"
+#include "exec-memory.h"
 
 typedef struct {
     CPUState *env;
@@ -76,8 +77,8 @@ static void lm32_evr_init(ram_addr_t ram_size_not_used,
 {
     CPUState *env;
     DriveInfo *dinfo;
-    ram_addr_t phys_ram;
-    ram_addr_t phys_flash;
+    MemoryRegion *address_space_mem =  get_system_memory();
+    MemoryRegion *phys_ram = g_new(MemoryRegion, 1);
     qemu_irq *cpu_irq, irq[32];
     ResetInfo *reset_info;
     int i;
@@ -105,13 +106,12 @@ static void lm32_evr_init(ram_addr_t ram_size_not_used,
 
     reset_info->flash_base = flash_base;
 
-    phys_ram = qemu_ram_alloc(NULL, "lm32_evr.sdram", ram_size);
-    cpu_register_physical_memory(ram_base, ram_size, phys_ram | IO_MEM_RAM);
+    memory_region_init_ram(phys_ram, NULL, "lm32_evr.sdram", ram_size);
+    memory_region_add_subregion(address_space_mem, ram_base, phys_ram);
 
-    phys_flash = qemu_ram_alloc(NULL, "lm32_evr.flash", flash_size);
     dinfo = drive_get(IF_PFLASH, 0, 0);
     /* Spansion S29NS128P */
-    pflash_cfi02_register(flash_base, phys_flash,
+    pflash_cfi02_register(flash_base, NULL, "lm32_evr.flash", flash_size,
                           dinfo ? dinfo->bdrv : NULL, flash_sector_size,
                           flash_size / flash_sector_size, 1, 2,
                           0x01, 0x7e, 0x43, 0x00, 0x555, 0x2aa, 1);
@@ -164,8 +164,8 @@ static void lm32_uclinux_init(ram_addr_t ram_size_not_used,
 {
     CPUState *env;
     DriveInfo *dinfo;
-    ram_addr_t phys_ram;
-    ram_addr_t phys_flash;
+    MemoryRegion *address_space_mem =  get_system_memory();
+    MemoryRegion *phys_ram = g_new(MemoryRegion, 1);
     qemu_irq *cpu_irq, irq[32];
     HWSetup *hw;
     ResetInfo *reset_info;
@@ -200,13 +200,12 @@ static void lm32_uclinux_init(ram_addr_t ram_size_not_used,
 
     reset_info->flash_base = flash_base;
 
-    phys_ram = qemu_ram_alloc(NULL, "lm32_uclinux.sdram", ram_size);
-    cpu_register_physical_memory(ram_base, ram_size, phys_ram | IO_MEM_RAM);
+    memory_region_init_ram(phys_ram, NULL, "lm32_uclinux.sdram", ram_size);
+    memory_region_add_subregion(address_space_mem, ram_base, phys_ram);
 
-    phys_flash = qemu_ram_alloc(NULL, "lm32_uclinux.flash", flash_size);
     dinfo = drive_get(IF_PFLASH, 0, 0);
     /* Spansion S29NS128P */
-    pflash_cfi02_register(flash_base, phys_flash,
+    pflash_cfi02_register(flash_base, NULL, "lm32_uclinux.flash", flash_size,
                           dinfo ? dinfo->bdrv : NULL, flash_sector_size,
                           flash_size / flash_sector_size, 1, 2,
                           0x01, 0x7e, 0x43, 0x00, 0x555, 0x2aa, 1);
diff --git a/hw/mainstone.c b/hw/mainstone.c
index 4792f0e3ed..336f31e64e 100644
--- a/hw/mainstone.c
+++ b/hw/mainstone.c
@@ -17,6 +17,7 @@
 #include "flash.h"
 #include "blockdev.h"
 #include "sysbus.h"
+#include "exec-memory.h"
 
 /* Device addresses */
 #define MST_FPGA_PHYS	0x08000000
@@ -90,7 +91,8 @@ static struct arm_boot_info mainstone_binfo = {
     .ram_size = 0x04000000,
 };
 
-static void mainstone_common_init(ram_addr_t ram_size,
+static void mainstone_common_init(MemoryRegion *address_space_mem,
+                ram_addr_t ram_size,
                 const char *kernel_filename,
                 const char *kernel_cmdline, const char *initrd_filename,
                 const char *cpu_model, enum mainstone_model_e model, int arm_id)
@@ -102,15 +104,16 @@ static void mainstone_common_init(ram_addr_t ram_size,
     DriveInfo *dinfo;
     int i;
     int be;
+    MemoryRegion *rom = g_new(MemoryRegion, 1);
 
     if (!cpu_model)
         cpu_model = "pxa270-c5";
 
     /* Setup CPU & memory */
     cpu = pxa270_init(mainstone_binfo.ram_size, cpu_model);
-    cpu_register_physical_memory(0, MAINSTONE_ROM,
-                    qemu_ram_alloc(NULL, "mainstone.rom",
-                                   MAINSTONE_ROM) | IO_MEM_ROM);
+    memory_region_init_ram(rom, NULL, "mainstone.rom", MAINSTONE_ROM);
+    memory_region_set_readonly(rom, true);
+    memory_region_add_subregion(address_space_mem, 0, rom);
 
 #ifdef TARGET_WORDS_BIGENDIAN
     be = 1;
@@ -126,10 +129,9 @@ static void mainstone_common_init(ram_addr_t ram_size,
             exit(1);
         }
 
-        if (!pflash_cfi01_register(mainstone_flash_base[i],
-                                   qemu_ram_alloc(NULL, i ? "mainstone.flash1" :
-                                                  "mainstone.flash0",
-                                                  MAINSTONE_FLASH),
+        if (!pflash_cfi01_register(mainstone_flash_base[i], NULL,
+                                   i ? "mainstone.flash1" : "mainstone.flash0",
+                                   MAINSTONE_FLASH,
                                    dinfo->bdrv, sector_len,
                                    MAINSTONE_FLASH / sector_len, 4, 0, 0, 0, 0,
                                    be)) {
@@ -170,7 +172,7 @@ static void mainstone_init(ram_addr_t ram_size,
                 const char *kernel_filename, const char *kernel_cmdline,
                 const char *initrd_filename, const char *cpu_model)
 {
-    mainstone_common_init(ram_size, kernel_filename,
+    mainstone_common_init(get_system_memory(), ram_size, kernel_filename,
                 kernel_cmdline, initrd_filename, cpu_model, mainstone, 0x196);
 }
 
diff --git a/hw/mcf5208.c b/hw/mcf5208.c
index 8fe507f82f..1c2c0c48aa 100644
--- a/hw/mcf5208.c
+++ b/hw/mcf5208.c
@@ -13,6 +13,7 @@
 #include "boards.h"
 #include "loader.h"
 #include "elf.h"
+#include "exec-memory.h"
 
 #define SYS_FREQ 66000000
 
@@ -27,6 +28,7 @@
 #define PCSR_PRE_MASK   0x0f00
 
 typedef struct {
+    MemoryRegion iomem;
     qemu_irq irq;
     ptimer_state *timer;
     uint16_t pcsr;
@@ -43,7 +45,7 @@ static void m5208_timer_update(m5208_timer_state *s)
 }
 
 static void m5208_timer_write(void *opaque, target_phys_addr_t offset,
-                              uint32_t value)
+                              uint64_t value, unsigned size)
 {
     m5208_timer_state *s = (m5208_timer_state *)opaque;
     int prescale;
@@ -104,7 +106,8 @@ static void m5208_timer_trigger(void *opaque)
     m5208_timer_update(s);
 }
 
-static uint32_t m5208_timer_read(void *opaque, target_phys_addr_t addr)
+static uint64_t m5208_timer_read(void *opaque, target_phys_addr_t addr,
+                                 unsigned size)
 {
     m5208_timer_state *s = (m5208_timer_state *)opaque;
     switch (addr) {
@@ -120,19 +123,14 @@ static uint32_t m5208_timer_read(void *opaque, target_phys_addr_t addr)
     }
 }
 
-static CPUReadMemoryFunc * const m5208_timer_readfn[] = {
-   m5208_timer_read,
-   m5208_timer_read,
-   m5208_timer_read
+static const MemoryRegionOps m5208_timer_ops = {
+    .read = m5208_timer_read,
+    .write = m5208_timer_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
-static CPUWriteMemoryFunc * const m5208_timer_writefn[] = {
-   m5208_timer_write,
-   m5208_timer_write,
-   m5208_timer_write
-};
-
-static uint32_t m5208_sys_read(void *opaque, target_phys_addr_t addr)
+static uint64_t m5208_sys_read(void *opaque, target_phys_addr_t addr,
+                               unsigned size)
 {
     switch (addr) {
     case 0x110: /* SDCS0 */
@@ -154,45 +152,36 @@ static uint32_t m5208_sys_read(void *opaque, target_phys_addr_t addr)
 }
 
 static void m5208_sys_write(void *opaque, target_phys_addr_t addr,
-                            uint32_t value)
+                            uint64_t value, unsigned size)
 {
     hw_error("m5208_sys_write: Bad offset 0x%x\n", (int)addr);
 }
 
-static CPUReadMemoryFunc * const m5208_sys_readfn[] = {
-   m5208_sys_read,
-   m5208_sys_read,
-   m5208_sys_read
-};
-
-static CPUWriteMemoryFunc * const m5208_sys_writefn[] = {
-   m5208_sys_write,
-   m5208_sys_write,
-   m5208_sys_write
+static const MemoryRegionOps m5208_sys_ops = {
+    .read = m5208_sys_read,
+    .write = m5208_sys_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
-static void mcf5208_sys_init(qemu_irq *pic)
+static void mcf5208_sys_init(MemoryRegion *address_space, qemu_irq *pic)
 {
-    int iomemtype;
+    MemoryRegion *iomem = g_new(MemoryRegion, 1);
     m5208_timer_state *s;
     QEMUBH *bh;
     int i;
 
-    iomemtype = cpu_register_io_memory(m5208_sys_readfn,
-                                       m5208_sys_writefn, NULL,
-                                       DEVICE_NATIVE_ENDIAN);
     /* SDRAMC.  */
-    cpu_register_physical_memory(0xfc0a8000, 0x00004000, iomemtype);
+    memory_region_init_io(iomem, &m5208_sys_ops, NULL, "m5208-sys", 0x00004000);
+    memory_region_add_subregion(address_space, 0xfc0a8000, iomem);
     /* Timers.  */
     for (i = 0; i < 2; i++) {
         s = (m5208_timer_state *)g_malloc0(sizeof(m5208_timer_state));
         bh = qemu_bh_new(m5208_timer_trigger, s);
         s->timer = ptimer_init(bh);
-        iomemtype = cpu_register_io_memory(m5208_timer_readfn,
-                                           m5208_timer_writefn, s,
-                                           DEVICE_NATIVE_ENDIAN);
-        cpu_register_physical_memory(0xfc080000 + 0x4000 * i, 0x00004000,
-                                     iomemtype);
+        memory_region_init_io(&s->iomem, &m5208_timer_ops, s,
+                              "m5208-timer", 0x00004000);
+        memory_region_add_subregion(address_space, 0xfc080000 + 0x4000 * i,
+                                    &s->iomem);
         s->irq = pic[4 + i];
     }
 }
@@ -207,6 +196,9 @@ static void mcf5208evb_init(ram_addr_t ram_size,
     uint64_t elf_entry;
     target_phys_addr_t entry;
     qemu_irq *pic;
+    MemoryRegion *address_space_mem = get_system_memory();
+    MemoryRegion *ram = g_new(MemoryRegion, 1);
+    MemoryRegion *sram = g_new(MemoryRegion, 1);
 
     if (!cpu_model)
         cpu_model = "m5208";
@@ -221,12 +213,12 @@ static void mcf5208evb_init(ram_addr_t ram_size,
     /* TODO: Configure BARs.  */
 
     /* DRAM at 0x40000000 */
-    cpu_register_physical_memory(0x40000000, ram_size,
-        qemu_ram_alloc(NULL, "mcf5208.ram", ram_size) | IO_MEM_RAM);
+    memory_region_init_ram(ram, NULL, "mcf5208.ram", ram_size);
+    memory_region_add_subregion(address_space_mem, 0x40000000, ram);
 
     /* Internal SRAM.  */
-    cpu_register_physical_memory(0x80000000, 16384,
-        qemu_ram_alloc(NULL, "mcf5208.sram", 16384) | IO_MEM_RAM);
+    memory_region_init_ram(sram, NULL, "mcf5208.sram", 16384);
+    memory_region_add_subregion(address_space_mem, 0x80000000, sram);
 
     /* Internal peripherals.  */
     pic = mcf_intc_init(0xfc048000, env);
@@ -235,7 +227,7 @@ static void mcf5208evb_init(ram_addr_t ram_size,
     mcf_uart_mm_init(0xfc064000, pic[27], serial_hds[1]);
     mcf_uart_mm_init(0xfc068000, pic[28], serial_hds[2]);
 
-    mcf5208_sys_init(pic);
+    mcf5208_sys_init(address_space_mem, pic);
 
     if (nb_nics > 1) {
         fprintf(stderr, "Too many NICs\n");
diff --git a/hw/milkymist-minimac2.c b/hw/milkymist-minimac2.c
index cd360264c1..fb48e37187 100644
--- a/hw/milkymist-minimac2.c
+++ b/hw/milkymist-minimac2.c
@@ -97,6 +97,8 @@ struct MilkymistMinimac2State {
     NICConf conf;
     char *phy_model;
     target_phys_addr_t buffers_base;
+    MemoryRegion buffers;
+    MemoryRegion regs_region;
 
     qemu_irq rx_irq;
     qemu_irq tx_irq;
@@ -320,8 +322,8 @@ static ssize_t minimac2_rx(VLANClientState *nc, const uint8_t *buf, size_t size)
     return size;
 }
 
-static uint32_t
-minimac2_read(void *opaque, target_phys_addr_t addr)
+static uint64_t
+minimac2_read(void *opaque, target_phys_addr_t addr, unsigned size)
 {
     MilkymistMinimac2State *s = opaque;
     uint32_t r = 0;
@@ -350,7 +352,8 @@ minimac2_read(void *opaque, target_phys_addr_t addr)
 }
 
 static void
-minimac2_write(void *opaque, target_phys_addr_t addr, uint32_t value)
+minimac2_write(void *opaque, target_phys_addr_t addr, uint64_t value,
+               unsigned size)
 {
     MilkymistMinimac2State *s = opaque;
 
@@ -395,16 +398,14 @@ minimac2_write(void *opaque, target_phys_addr_t addr, uint32_t value)
     }
 }
 
-static CPUReadMemoryFunc * const minimac2_read_fn[] = {
-    NULL,
-    NULL,
-    &minimac2_read,
-};
-
-static CPUWriteMemoryFunc * const minimac2_write_fn[] = {
-    NULL,
-    NULL,
-    &minimac2_write,
+static const MemoryRegionOps minimac2_ops = {
+    .read = minimac2_read,
+    .write = minimac2_write,
+    .valid = {
+        .min_access_size = 4,
+        .max_access_size = 4,
+    },
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static int minimac2_can_rx(VLANClientState *nc)
@@ -457,25 +458,23 @@ static NetClientInfo net_milkymist_minimac2_info = {
 static int milkymist_minimac2_init(SysBusDevice *dev)
 {
     MilkymistMinimac2State *s = FROM_SYSBUS(typeof(*s), dev);
-    int regs;
-    ram_addr_t buffers;
     size_t buffers_size = TARGET_PAGE_ALIGN(3 * MINIMAC2_BUFFER_SIZE);
 
     sysbus_init_irq(dev, &s->rx_irq);
     sysbus_init_irq(dev, &s->tx_irq);
 
-    regs = cpu_register_io_memory(minimac2_read_fn, minimac2_write_fn, s,
-            DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio(dev, R_MAX * 4, regs);
+    memory_region_init_io(&s->regs_region, &minimac2_ops, s,
+                          "minimac2-mmio", R_MAX * 4);
+    sysbus_init_mmio_region(dev, &s->regs_region);
 
     /* register buffers memory */
-    buffers = qemu_ram_alloc(NULL, "milkymist_minimac2.buffers", buffers_size);
-    s->rx0_buf = qemu_get_ram_ptr(buffers);
+    memory_region_init_ram(&s->buffers, NULL, "milkymist_minimac2.buffers",
+                           buffers_size);
+    s->rx0_buf = memory_region_get_ram_ptr(&s->buffers);
     s->rx1_buf = s->rx0_buf + MINIMAC2_BUFFER_SIZE;
     s->tx_buf = s->rx1_buf + MINIMAC2_BUFFER_SIZE;
 
-    cpu_register_physical_memory(s->buffers_base, buffers_size,
-            buffers | IO_MEM_RAM);
+    sysbus_add_memory(dev, s->buffers_base, &s->buffers);
 
     qemu_macaddr_default_if_unset(&s->conf.macaddr);
     s->nic = qemu_new_nic(&net_milkymist_minimac2_info, &s->conf,
diff --git a/hw/milkymist-softusb.c b/hw/milkymist-softusb.c
index fe4eedb2cb..ef4d9ee2ce 100644
--- a/hw/milkymist-softusb.c
+++ b/hw/milkymist-softusb.c
@@ -49,6 +49,9 @@ struct MilkymistSoftUsbState {
     HIDState hid_kbd;
     HIDState hid_mouse;
 
+    MemoryRegion regs_region;
+    MemoryRegion pmem;
+    MemoryRegion dmem;
     qemu_irq irq;
 
     /* device properties */
@@ -68,7 +71,8 @@ struct MilkymistSoftUsbState {
 };
 typedef struct MilkymistSoftUsbState MilkymistSoftUsbState;
 
-static uint32_t softusb_read(void *opaque, target_phys_addr_t addr)
+static uint64_t softusb_read(void *opaque, target_phys_addr_t addr,
+                             unsigned size)
 {
     MilkymistSoftUsbState *s = opaque;
     uint32_t r = 0;
@@ -91,7 +95,8 @@ static uint32_t softusb_read(void *opaque, target_phys_addr_t addr)
 }
 
 static void
-softusb_write(void *opaque, target_phys_addr_t addr, uint32_t value)
+softusb_write(void *opaque, target_phys_addr_t addr, uint64_t value,
+              unsigned size)
 {
     MilkymistSoftUsbState *s = opaque;
 
@@ -110,16 +115,14 @@ softusb_write(void *opaque, target_phys_addr_t addr, uint32_t value)
     }
 }
 
-static CPUReadMemoryFunc * const softusb_read_fn[] = {
-    NULL,
-    NULL,
-    &softusb_read,
-};
-
-static CPUWriteMemoryFunc * const softusb_write_fn[] = {
-    NULL,
-    NULL,
-    &softusb_write,
+static const MemoryRegionOps softusb_mmio_ops = {
+    .read = softusb_read,
+    .write = softusb_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+    .valid = {
+        .min_access_size = 4,
+        .max_access_size = 4,
+    },
 };
 
 static inline void softusb_read_dmem(MilkymistSoftUsbState *s,
@@ -256,23 +259,20 @@ static void milkymist_softusb_reset(DeviceState *d)
 static int milkymist_softusb_init(SysBusDevice *dev)
 {
     MilkymistSoftUsbState *s = FROM_SYSBUS(typeof(*s), dev);
-    int softusb_regs;
-    ram_addr_t pmem_ram;
-    ram_addr_t dmem_ram;
 
     sysbus_init_irq(dev, &s->irq);
 
-    softusb_regs = cpu_register_io_memory(softusb_read_fn, softusb_write_fn, s,
-            DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio(dev, R_MAX * 4, softusb_regs);
+    memory_region_init_io(&s->regs_region, &softusb_mmio_ops, s,
+                          "milkymist-softusb", R_MAX * 4);
+    sysbus_init_mmio_region(dev, &s->regs_region);
 
     /* register pmem and dmem */
-    pmem_ram = qemu_ram_alloc(NULL, "milkymist_softusb.pmem", s->pmem_size);
-    cpu_register_physical_memory(s->pmem_base, s->pmem_size,
-            pmem_ram | IO_MEM_RAM);
-    dmem_ram = qemu_ram_alloc(NULL, "milkymist_softusb.dmem", s->dmem_size);
-    cpu_register_physical_memory(s->dmem_base, s->dmem_size,
-            dmem_ram | IO_MEM_RAM);
+    memory_region_init_ram(&s->pmem, NULL, "milkymist_softusb.pmem",
+                           s->pmem_size);
+    sysbus_add_memory(dev, s->pmem_base, &s->pmem);
+    memory_region_init_ram(&s->dmem, NULL, "milkymist_softusb.dmem",
+                           s->dmem_size);
+    sysbus_add_memory(dev, s->dmem_base, &s->dmem);
 
     hid_init(&s->hid_kbd, HID_KEYBOARD, softusb_kbd_hid_datain);
     hid_init(&s->hid_mouse, HID_MOUSE, softusb_mouse_hid_datain);
diff --git a/hw/milkymist.c b/hw/milkymist.c
index 93288c8401..bca0a58d8c 100644
--- a/hw/milkymist.c
+++ b/hw/milkymist.c
@@ -29,6 +29,7 @@
 #include "blockdev.h"
 #include "milkymist-hw.h"
 #include "lm32.h"
+#include "exec-memory.h"
 
 #define BIOS_FILENAME    "mmone-bios.bin"
 #define BIOS_OFFSET      0x00860000
@@ -81,8 +82,8 @@ milkymist_init(ram_addr_t ram_size_not_used,
     CPUState *env;
     int kernel_size;
     DriveInfo *dinfo;
-    ram_addr_t phys_sdram;
-    ram_addr_t phys_flash;
+    MemoryRegion *address_space_mem = get_system_memory();
+    MemoryRegion *phys_sdram = g_new(MemoryRegion, 1);
     qemu_irq irq[32], *cpu_irq;
     int i;
     char *bios_filename;
@@ -109,14 +110,12 @@ milkymist_init(ram_addr_t ram_size_not_used,
 
     cpu_lm32_set_phys_msb_ignore(env, 1);
 
-    phys_sdram = qemu_ram_alloc(NULL, "milkymist.sdram", sdram_size);
-    cpu_register_physical_memory(sdram_base, sdram_size,
-            phys_sdram | IO_MEM_RAM);
+    memory_region_init_ram(phys_sdram, NULL, "milkymist.sdram", sdram_size);
+    memory_region_add_subregion(address_space_mem, sdram_base, phys_sdram);
 
-    phys_flash = qemu_ram_alloc(NULL, "milkymist.flash", flash_size);
     dinfo = drive_get(IF_PFLASH, 0, 0);
     /* Numonyx JS28F256J3F105 */
-    pflash_cfi01_register(flash_base, phys_flash,
+    pflash_cfi01_register(flash_base, NULL, "milkymist.flash", flash_size,
                           dinfo ? dinfo->bdrv : NULL, flash_sector_size,
                           flash_size / flash_sector_size, 2,
                           0x00, 0x89, 0x00, 0x1d, 1);
diff --git a/hw/mips_fulong2e.c b/hw/mips_fulong2e.c
index ec8c88e2e1..abe30569f2 100644
--- a/hw/mips_fulong2e.c
+++ b/hw/mips_fulong2e.c
@@ -38,6 +38,7 @@
 #include "vt82c686.h"
 #include "mc146818rtc.h"
 #include "blockdev.h"
+#include "exec-memory.h"
 
 #define DEBUG_FULONG2E_INIT
 
@@ -256,7 +257,9 @@ static void mips_fulong2e_init(ram_addr_t ram_size, const char *boot_device,
                         const char *initrd_filename, const char *cpu_model)
 {
     char *filename;
-    unsigned long ram_offset, bios_offset;
+    MemoryRegion *address_space_mem = get_system_memory();
+    MemoryRegion *ram = g_new(MemoryRegion, 1);
+    MemoryRegion *bios = g_new(MemoryRegion, 1);
     long bios_size;
     int64_t kernel_entry;
     qemu_irq *i8259;
@@ -288,12 +291,12 @@ static void mips_fulong2e_init(ram_addr_t ram_size, const char *boot_device,
     bios_size = 1024 * 1024;
 
     /* allocate RAM */
-    ram_offset = qemu_ram_alloc(NULL, "fulong2e.ram", ram_size);
-    bios_offset = qemu_ram_alloc(NULL, "fulong2e.bios", bios_size);
+    memory_region_init_ram(ram, NULL, "fulong2e.ram", ram_size);
+    memory_region_init_ram(bios, NULL, "fulong2e.bios", bios_size);
+    memory_region_set_readonly(bios, true);
 
-    cpu_register_physical_memory(0, ram_size, ram_offset);
-    cpu_register_physical_memory(0x1fc00000LL,
-					   bios_size, bios_offset | IO_MEM_ROM);
+    memory_region_add_subregion(address_space_mem, 0, ram);
+    memory_region_add_subregion(address_space_mem, 0x1fc00000LL, bios);
 
     /* We do not support flash operation, just loading pmon.bin as raw BIOS.
      * Please use -L to set the BIOS path and -bios to set bios name. */
@@ -304,7 +307,7 @@ static void mips_fulong2e_init(ram_addr_t ram_size, const char *boot_device,
         loaderparams.kernel_cmdline = kernel_cmdline;
         loaderparams.initrd_filename = initrd_filename;
         kernel_entry = load_kernel (env);
-        write_bootloader(env, qemu_get_ram_ptr(bios_offset), kernel_entry);
+        write_bootloader(env, memory_region_get_ram_ptr(bios), kernel_entry);
     } else {
         if (bios_name == NULL) {
                 bios_name = FULONG_BIOSNAME;
diff --git a/hw/mips_malta.c b/hw/mips_malta.c
index a0adb566ab..e7cdf2091b 100644
--- a/hw/mips_malta.c
+++ b/hw/mips_malta.c
@@ -46,6 +46,7 @@
 #include "elf.h"
 #include "mc146818rtc.h"
 #include "blockdev.h"
+#include "exec-memory.h"
 
 //#define DEBUG_BOARD_INIT
 
@@ -769,8 +770,10 @@ void mips_malta_init (ram_addr_t ram_size,
                       const char *initrd_filename, const char *cpu_model)
 {
     char *filename;
+    pflash_t *fl;
     ram_addr_t ram_offset;
-    ram_addr_t bios_offset;
+    MemoryRegion *system_memory = get_system_memory();
+    MemoryRegion *bios, *bios_alias = g_new(MemoryRegion, 1);
     target_long bios_size;
     int64_t kernel_entry;
     PCIBus *pci_bus;
@@ -826,17 +829,9 @@ void mips_malta_init (ram_addr_t ram_size,
         exit(1);
     }
     ram_offset = qemu_ram_alloc(NULL, "mips_malta.ram", ram_size);
-    bios_offset = qemu_ram_alloc(NULL, "mips_malta.bios", BIOS_SIZE);
-
 
     cpu_register_physical_memory(0, ram_size, ram_offset | IO_MEM_RAM);
 
-    /* Map the bios at two physical locations, as on the real board. */
-    cpu_register_physical_memory(0x1e000000LL,
-                                 BIOS_SIZE, bios_offset | IO_MEM_ROM);
-    cpu_register_physical_memory(0x1fc00000LL,
-                                 BIOS_SIZE, bios_offset | IO_MEM_ROM);
-
 #ifdef TARGET_WORDS_BIGENDIAN
     be = 1;
 #else
@@ -848,12 +843,19 @@ void mips_malta_init (ram_addr_t ram_size,
     /* Load firmware in flash / BIOS unless we boot directly into a kernel. */
     if (kernel_filename) {
         /* Write a small bootloader to the flash location. */
+        bios = g_new(MemoryRegion, 1);
+        memory_region_init_ram(bios, NULL, "mips_malta.bios", BIOS_SIZE);
+        memory_region_set_readonly(bios, true);
+        memory_region_init_alias(bios_alias, "bios.1fc", bios, 0, BIOS_SIZE);
+        /* Map the bios at two physical locations, as on the real board. */
+        memory_region_add_subregion(system_memory, 0x1e000000LL, bios);
+        memory_region_add_subregion(system_memory, 0x1fc00000LL, bios_alias);
         loaderparams.ram_size = ram_size;
         loaderparams.kernel_filename = kernel_filename;
         loaderparams.kernel_cmdline = kernel_cmdline;
         loaderparams.initrd_filename = initrd_filename;
         kernel_entry = load_kernel();
-        write_bootloader(env, qemu_get_ram_ptr(bios_offset), kernel_entry);
+        write_bootloader(env, memory_region_get_ram_ptr(bios), kernel_entry);
     } else {
         dinfo = drive_get(IF_PFLASH, 0, fl_idx);
         if (dinfo) {
@@ -862,15 +864,31 @@ void mips_malta_init (ram_addr_t ram_size,
             fl_sectors = bios_size >> 16;
 #ifdef DEBUG_BOARD_INIT
             printf("Register parallel flash %d size " TARGET_FMT_lx " at "
-                   "offset %08lx addr %08llx '%s' %x\n",
-                   fl_idx, bios_size, bios_offset, 0x1e000000LL,
+                   "addr %08llx '%s' %x\n",
+                   fl_idx, bios_size, 0x1e000000LL,
                    bdrv_get_device_name(dinfo->bdrv), fl_sectors);
 #endif
-            pflash_cfi01_register(0x1e000000LL, bios_offset,
-                                  dinfo->bdrv, 65536, fl_sectors,
-                                  4, 0x0000, 0x0000, 0x0000, 0x0000, be);
-            fl_idx++;
+            fl = pflash_cfi01_register(0x1e000000LL,
+                                       NULL, "mips_malta.bios", BIOS_SIZE,
+                                       dinfo->bdrv, 65536, fl_sectors,
+                                       4, 0x0000, 0x0000, 0x0000, 0x0000, be);
+            bios = pflash_cfi01_get_memory(fl);
+            /* Map the bios at two physical locations, as on the real board. */
+            memory_region_init_alias(bios_alias, "bios.1fc",
+                                     bios, 0, BIOS_SIZE);
+            memory_region_add_subregion(system_memory, 0x1fc00000LL,
+                                        bios_alias);
+           fl_idx++;
         } else {
+            bios = g_new(MemoryRegion, 1);
+            memory_region_init_ram(bios, NULL, "mips_malta.bios", BIOS_SIZE);
+            memory_region_set_readonly(bios, true);
+            memory_region_init_alias(bios_alias, "bios.1fc",
+                                     bios, 0, BIOS_SIZE);
+            /* Map the bios at two physical locations, as on the real board. */
+            memory_region_add_subregion(system_memory, 0x1e000000LL, bios);
+            memory_region_add_subregion(system_memory, 0x1fc00000LL,
+                                        bios_alias);
             /* Load a BIOS image. */
             if (bios_name == NULL)
                 bios_name = BIOS_FILENAME;
@@ -893,7 +911,7 @@ void mips_malta_init (ram_addr_t ram_size,
            a neat trick which allows bi-endian firmware. */
 #ifndef TARGET_WORDS_BIGENDIAN
         {
-            uint32_t *addr = qemu_get_ram_ptr(bios_offset);;
+            uint32_t *addr = memory_region_get_ram_ptr(bios);
             uint32_t *end = addr + bios_size;
             while (addr < end) {
                 bswap32s(addr);
@@ -905,7 +923,7 @@ void mips_malta_init (ram_addr_t ram_size,
     /* Board ID = 0x420 (Malta Board with CoreLV)
        XXX: theoretically 0x1e000010 should map to flash and 0x1fc00010 should
        map to the board ID. */
-    stl_p(qemu_get_ram_ptr(bios_offset) + 0x10, 0x00000420);
+    stl_p(memory_region_get_ram_ptr(bios) + 0x10, 0x00000420);
 
     /* Init internal devices */
     cpu_mips_irq_init_cpu(env);
diff --git a/hw/mips_r4k.c b/hw/mips_r4k.c
index 9d90568e4e..5d002c5a2b 100644
--- a/hw/mips_r4k.c
+++ b/hw/mips_r4k.c
@@ -23,6 +23,7 @@
 #include "elf.h"
 #include "mc146818rtc.h"
 #include "blockdev.h"
+#include "exec-memory.h"
 
 #define MAX_IDE_BUS 2
 
@@ -163,7 +164,7 @@ void mips_r4k_init (ram_addr_t ram_size,
 {
     char *filename;
     ram_addr_t ram_offset;
-    ram_addr_t bios_offset;
+    MemoryRegion *bios;
     int bios_size;
     CPUState *env;
     ResetData *reset_info;
@@ -227,15 +228,15 @@ void mips_r4k_init (ram_addr_t ram_size,
     be = 0;
 #endif
     if ((bios_size > 0) && (bios_size <= BIOS_SIZE)) {
-        bios_offset = qemu_ram_alloc(NULL, "mips_r4k.bios", BIOS_SIZE);
-	cpu_register_physical_memory(0x1fc00000, BIOS_SIZE,
-                                     bios_offset | IO_MEM_ROM);
+        bios = g_new(MemoryRegion, 1);
+        memory_region_init_ram(bios, NULL, "mips_r4k.bios", BIOS_SIZE);
+        memory_region_set_readonly(bios, true);
+        memory_region_add_subregion(get_system_memory(), 0x1fc00000, bios);
 
         load_image_targphys(filename, 0x1fc00000, BIOS_SIZE);
     } else if ((dinfo = drive_get(IF_PFLASH, 0, 0)) != NULL) {
         uint32_t mips_rom = 0x00400000;
-        bios_offset = qemu_ram_alloc(NULL, "mips_r4k.bios", mips_rom);
-        if (!pflash_cfi01_register(0x1fc00000, bios_offset,
+        if (!pflash_cfi01_register(0x1fc00000, NULL, "mips_r4k.bios", mips_rom,
                                    dinfo->bdrv, sector_len,
                                    mips_rom / sector_len,
                                    4, 0, 0, 0, 0, be)) {
diff --git a/hw/musicpal.c b/hw/musicpal.c
index 63dd391176..ade5a91feb 100644
--- a/hw/musicpal.c
+++ b/hw/musicpal.c
@@ -1565,16 +1565,16 @@ static void musicpal_init(ram_addr_t ram_size,
          * image is smaller than 32 MB.
          */
 #ifdef TARGET_WORDS_BIGENDIAN
-        pflash_cfi02_register(0-MP_FLASH_SIZE_MAX, qemu_ram_alloc(NULL,
-                              "musicpal.flash", flash_size),
+        pflash_cfi02_register(0-MP_FLASH_SIZE_MAX, NULL,
+                              "musicpal.flash", flash_size,
                               dinfo->bdrv, 0x10000,
                               (flash_size + 0xffff) >> 16,
                               MP_FLASH_SIZE_MAX / flash_size,
                               2, 0x00BF, 0x236D, 0x0000, 0x0000,
                               0x5555, 0x2AAA, 1);
 #else
-        pflash_cfi02_register(0-MP_FLASH_SIZE_MAX, qemu_ram_alloc(NULL,
-                              "musicpal.flash", flash_size),
+        pflash_cfi02_register(0-MP_FLASH_SIZE_MAX, NULL,
+                              "musicpal.flash", flash_size,
                               dinfo->bdrv, 0x10000,
                               (flash_size + 0xffff) >> 16,
                               MP_FLASH_SIZE_MAX / flash_size,
diff --git a/hw/omap_sx1.c b/hw/omap_sx1.c
index a7b687bc41..15cfbb52f3 100644
--- a/hw/omap_sx1.c
+++ b/hw/omap_sx1.c
@@ -161,8 +161,8 @@ static void sx1_init(ram_addr_t ram_size,
 #endif
 
     if ((dinfo = drive_get(IF_PFLASH, 0, fl_idx)) != NULL) {
-        if (!pflash_cfi01_register(OMAP_CS0_BASE, qemu_ram_alloc(NULL,
-                                   "omap_sx1.flash0-1", flash_size),
+        if (!pflash_cfi01_register(OMAP_CS0_BASE, NULL,
+                                   "omap_sx1.flash0-1", flash_size,
                                    dinfo->bdrv, sector_size,
                                    flash_size / sector_size,
                                    4, 0, 0, 0, 0, be)) {
@@ -182,8 +182,8 @@ static void sx1_init(ram_addr_t ram_size,
         cpu_register_physical_memory(OMAP_CS1_BASE + flash1_size,
                         OMAP_CS1_SIZE - flash1_size, io);
 
-        if (!pflash_cfi01_register(OMAP_CS1_BASE, qemu_ram_alloc(NULL,
-                                   "omap_sx1.flash1-1", flash1_size),
+        if (!pflash_cfi01_register(OMAP_CS1_BASE, NULL,
+                                   "omap_sx1.flash1-1", flash1_size,
                                    dinfo->bdrv, sector_size,
                                    flash1_size / sector_size,
                                    4, 0, 0, 0, 0, be)) {
diff --git a/hw/pci_host.c b/hw/pci_host.c
index 2e8a29f1e3..44c6c207a9 100644
--- a/hw/pci_host.c
+++ b/hw/pci_host.c
@@ -94,82 +94,72 @@ uint32_t pci_data_read(PCIBus *s, uint32_t addr, int len)
     return val;
 }
 
-static void pci_host_config_write(ReadWriteHandler *handler,
-                                  pcibus_t addr, uint32_t val, int len)
+static void pci_host_config_write(void *opaque, target_phys_addr_t addr,
+                                  uint64_t val, unsigned len)
 {
-    PCIHostState *s = container_of(handler, PCIHostState, conf_handler);
+    PCIHostState *s = opaque;
 
-    PCI_DPRINTF("%s addr %" FMT_PCIBUS " %d val %"PRIx32"\n",
+    PCI_DPRINTF("%s addr " TARGET_FMT_plx " len %d val %"PRIx64"\n",
                 __func__, addr, len, val);
     s->config_reg = val;
 }
 
-static uint32_t pci_host_config_read(ReadWriteHandler *handler,
-                                     pcibus_t addr, int len)
+static uint64_t pci_host_config_read(void *opaque, target_phys_addr_t addr,
+                                     unsigned len)
 {
-    PCIHostState *s = container_of(handler, PCIHostState, conf_handler);
+    PCIHostState *s = opaque;
     uint32_t val = s->config_reg;
 
-    PCI_DPRINTF("%s addr %" FMT_PCIBUS " len %d val %"PRIx32"\n",
+    PCI_DPRINTF("%s addr " TARGET_FMT_plx " len %d val %"PRIx32"\n",
                 __func__, addr, len, val);
     return val;
 }
 
-static void pci_host_data_write(ReadWriteHandler *handler,
-                                pcibus_t addr, uint32_t val, int len)
+static void pci_host_data_write(void *opaque, target_phys_addr_t addr,
+                                uint64_t val, unsigned len)
 {
-    PCIHostState *s = container_of(handler, PCIHostState, data_handler);
-    PCI_DPRINTF("write addr %" FMT_PCIBUS " len %d val %x\n",
-                addr, len, val);
+    PCIHostState *s = opaque;
+    PCI_DPRINTF("write addr " TARGET_FMT_plx " len %d val %x\n",
+                addr, len, (unsigned)val);
     if (s->config_reg & (1u << 31))
         pci_data_write(s->bus, s->config_reg | (addr & 3), val, len);
 }
 
-static uint32_t pci_host_data_read(ReadWriteHandler *handler,
-                                   pcibus_t addr, int len)
+static uint64_t pci_host_data_read(void *opaque,
+                                   target_phys_addr_t addr, unsigned len)
 {
-    PCIHostState *s = container_of(handler, PCIHostState, data_handler);
+    PCIHostState *s = opaque;
     uint32_t val;
     if (!(s->config_reg & (1 << 31)))
         return 0xffffffff;
     val = pci_data_read(s->bus, s->config_reg | (addr & 3), len);
-    PCI_DPRINTF("read addr %" FMT_PCIBUS " len %d val %x\n",
+    PCI_DPRINTF("read addr " TARGET_FMT_plx " len %d val %x\n",
                 addr, len, val);
     return val;
 }
 
-static void pci_host_init(PCIHostState *s)
-{
-    s->conf_handler.write = pci_host_config_write;
-    s->conf_handler.read = pci_host_config_read;
-    s->data_handler.write = pci_host_data_write;
-    s->data_handler.read = pci_host_data_read;
-}
+const MemoryRegionOps pci_host_conf_le_ops = {
+    .read = pci_host_config_read,
+    .write = pci_host_config_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+};
 
-int pci_host_conf_register_mmio(PCIHostState *s, int endian)
-{
-    pci_host_init(s);
-    return cpu_register_io_memory_simple(&s->conf_handler, endian);
-}
+const MemoryRegionOps pci_host_conf_be_ops = {
+    .read = pci_host_config_read,
+    .write = pci_host_config_write,
+    .endianness = DEVICE_BIG_ENDIAN,
+};
 
-void pci_host_conf_register_ioport(pio_addr_t ioport, PCIHostState *s)
-{
-    pci_host_init(s);
-    register_ioport_simple(&s->conf_handler, ioport, 4, 4);
-    sysbus_init_ioports(&s->busdev, ioport, 4);
-}
+const MemoryRegionOps pci_host_data_le_ops = {
+    .read = pci_host_data_read,
+    .write = pci_host_data_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+};
+
+const MemoryRegionOps pci_host_data_be_ops = {
+    .read = pci_host_data_read,
+    .write = pci_host_data_write,
+    .endianness = DEVICE_BIG_ENDIAN,
+};
 
-int pci_host_data_register_mmio(PCIHostState *s, int endian)
-{
-    pci_host_init(s);
-    return cpu_register_io_memory_simple(&s->data_handler, endian);
-}
 
-void pci_host_data_register_ioport(pio_addr_t ioport, PCIHostState *s)
-{
-    pci_host_init(s);
-    register_ioport_simple(&s->data_handler, ioport, 4, 1);
-    register_ioport_simple(&s->data_handler, ioport, 4, 2);
-    register_ioport_simple(&s->data_handler, ioport, 4, 4);
-    sysbus_init_ioports(&s->busdev, ioport, 4);
-}
diff --git a/hw/pci_host.h b/hw/pci_host.h
index 7f551143bb..0211086d70 100644
--- a/hw/pci_host.h
+++ b/hw/pci_host.h
@@ -29,12 +29,11 @@
 #define PCI_HOST_H
 
 #include "sysbus.h"
-#include "rwhandler.h"
 
 struct PCIHostState {
     SysBusDevice busdev;
-    ReadWriteHandler conf_handler;
-    ReadWriteHandler data_handler;
+    MemoryRegion conf_mem;
+    MemoryRegion data_mem;
     MemoryRegion *address_space;
     uint32_t config_reg;
     PCIBus *bus;
@@ -49,12 +48,9 @@ uint32_t pci_host_config_read_common(PCIDevice *pci_dev, uint32_t addr,
 void pci_data_write(PCIBus *s, uint32_t addr, uint32_t val, int len);
 uint32_t pci_data_read(PCIBus *s, uint32_t addr, int len);
 
-/* for mmio */
-int pci_host_conf_register_mmio(PCIHostState *s, int endian);
-int pci_host_data_register_mmio(PCIHostState *s, int endian);
-
-/* for ioio */
-void pci_host_conf_register_ioport(pio_addr_t ioport, PCIHostState *s);
-void pci_host_data_register_ioport(pio_addr_t ioport, PCIHostState *s);
+extern const MemoryRegionOps pci_host_conf_le_ops;
+extern const MemoryRegionOps pci_host_conf_be_ops;
+extern const MemoryRegionOps pci_host_data_le_ops;
+extern const MemoryRegionOps pci_host_data_be_ops;
 
 #endif /* PCI_HOST_H */
diff --git a/hw/petalogix_ml605_mmu.c b/hw/petalogix_ml605_mmu.c
index e3ca310efd..38db521b37 100644
--- a/hw/petalogix_ml605_mmu.c
+++ b/hw/petalogix_ml605_mmu.c
@@ -149,7 +149,6 @@ petalogix_ml605_init(ram_addr_t ram_size,
     target_phys_addr_t ddr_base = MEMORY_BASEADDR;
     ram_addr_t phys_lmb_bram;
     ram_addr_t phys_ram;
-    ram_addr_t phys_flash;
     qemu_irq irq[32], *cpu_irq;
 
     /* init CPUs */
@@ -169,11 +168,11 @@ petalogix_ml605_init(ram_addr_t ram_size,
     phys_ram = qemu_ram_alloc(NULL, "petalogix_ml605.ram", ram_size);
     cpu_register_physical_memory(ddr_base, ram_size, phys_ram | IO_MEM_RAM);
 
-    phys_flash = qemu_ram_alloc(NULL, "petalogix_ml605.flash", FLASH_SIZE);
     dinfo = drive_get(IF_PFLASH, 0, 0);
     /* 5th parameter 2 means bank-width
      * 10th paremeter 0 means little-endian */
-    pflash_cfi01_register(FLASH_BASEADDR, phys_flash,
+    pflash_cfi01_register(FLASH_BASEADDR,
+                          NULL, "petalogix_ml605.flash", FLASH_SIZE,
                           dinfo ? dinfo->bdrv : NULL, (64 * 1024),
                           FLASH_SIZE >> 16,
                           2, 0x89, 0x18, 0x0000, 0x0, 0);
diff --git a/hw/petalogix_s3adsp1800_mmu.c b/hw/petalogix_s3adsp1800_mmu.c
index a43fb4c95c..66fb96d8eb 100644
--- a/hw/petalogix_s3adsp1800_mmu.c
+++ b/hw/petalogix_s3adsp1800_mmu.c
@@ -127,7 +127,6 @@ petalogix_s3adsp1800_init(ram_addr_t ram_size,
     target_phys_addr_t ddr_base = 0x90000000;
     ram_addr_t phys_lmb_bram;
     ram_addr_t phys_ram;
-    ram_addr_t phys_flash;
     qemu_irq irq[32], *cpu_irq;
 
     /* init CPUs */
@@ -148,9 +147,9 @@ petalogix_s3adsp1800_init(ram_addr_t ram_size,
     phys_ram = qemu_ram_alloc(NULL, "petalogix_s3adsp1800.ram", ram_size);
     cpu_register_physical_memory(ddr_base, ram_size, phys_ram | IO_MEM_RAM);
 
-    phys_flash = qemu_ram_alloc(NULL, "petalogix_s3adsp1800.flash", FLASH_SIZE);
     dinfo = drive_get(IF_PFLASH, 0, 0);
-    pflash_cfi01_register(0xa0000000, phys_flash,
+    pflash_cfi01_register(0xa0000000,
+                          NULL, "petalogix_s3adsp1800.flash", FLASH_SIZE,
                           dinfo ? dinfo->bdrv : NULL, (64 * 1024),
                           FLASH_SIZE >> 16,
                           1, 0x89, 0x18, 0x0000, 0x0, 1);
diff --git a/hw/pflash_cfi01.c b/hw/pflash_cfi01.c
index 90e1301c5e..69b8e3d539 100644
--- a/hw/pflash_cfi01.c
+++ b/hw/pflash_cfi01.c
@@ -40,6 +40,7 @@
 #include "flash.h"
 #include "block.h"
 #include "qemu-timer.h"
+#include "exec-memory.h"
 
 #define PFLASH_BUG(fmt, ...) \
 do { \
@@ -74,8 +75,7 @@ struct pflash_t {
     target_phys_addr_t counter;
     unsigned int writeblock_size;
     QEMUTimer *timer;
-    ram_addr_t off;
-    int fl_mem;
+    MemoryRegion mem;
     void *storage;
 };
 
@@ -89,8 +89,7 @@ static void pflash_timer (void *opaque)
     if (pfl->bypass) {
         pfl->wcycle = 2;
     } else {
-        cpu_register_physical_memory(pfl->base, pfl->total_len,
-                        pfl->off | IO_MEM_ROMD | pfl->fl_mem);
+        memory_region_rom_device_set_readable(&pfl->mem, true);
         pfl->wcycle = 0;
     }
     pfl->cmd = 0;
@@ -263,7 +262,7 @@ static void pflash_write(pflash_t *pfl, target_phys_addr_t offset,
 
     if (!pfl->wcycle) {
         /* Set the device in I/O access mode */
-        cpu_register_physical_memory(pfl->base, pfl->total_len, pfl->fl_mem);
+        memory_region_rom_device_set_readable(&pfl->mem, false);
     }
 
     switch (pfl->wcycle) {
@@ -422,8 +421,7 @@ static void pflash_write(pflash_t *pfl, target_phys_addr_t offset,
            __func__, offset, pfl->wcycle, pfl->cmd, value);
 
  reset_flash:
-    cpu_register_physical_memory(pfl->base, pfl->total_len,
-                    pfl->off | IO_MEM_ROMD | pfl->fl_mem);
+    memory_region_rom_device_set_readable(&pfl->mem, true);
 
     pfl->bypass = 0;
     pfl->wcycle = 0;
@@ -514,28 +512,20 @@ static void pflash_writel_le(void *opaque, target_phys_addr_t addr,
     pflash_write(pfl, addr, value, 4, 0);
 }
 
-static CPUWriteMemoryFunc * const pflash_write_ops_be[] = {
-    &pflash_writeb_be,
-    &pflash_writew_be,
-    &pflash_writel_be,
+static const MemoryRegionOps pflash_cfi01_ops_be = {
+    .old_mmio = {
+        .read = { pflash_readb_be, pflash_readw_be, pflash_readl_be, },
+        .write = { pflash_writeb_be, pflash_writew_be, pflash_writel_be, },
+    },
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
-static CPUReadMemoryFunc * const pflash_read_ops_be[] = {
-    &pflash_readb_be,
-    &pflash_readw_be,
-    &pflash_readl_be,
-};
-
-static CPUWriteMemoryFunc * const pflash_write_ops_le[] = {
-    &pflash_writeb_le,
-    &pflash_writew_le,
-    &pflash_writel_le,
-};
-
-static CPUReadMemoryFunc * const pflash_read_ops_le[] = {
-    &pflash_readb_le,
-    &pflash_readw_le,
-    &pflash_readl_le,
+static const MemoryRegionOps pflash_cfi01_ops_le = {
+    .old_mmio = {
+        .read = { pflash_readb_le, pflash_readw_le, pflash_readl_le, },
+        .write = { pflash_writeb_le, pflash_writew_le, pflash_writel_le, },
+    },
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 /* Count trailing zeroes of a 32 bits quantity */
@@ -574,12 +564,13 @@ static int ctz32 (uint32_t n)
     return ret;
 }
 
-pflash_t *pflash_cfi01_register(target_phys_addr_t base, ram_addr_t off,
+pflash_t *pflash_cfi01_register(target_phys_addr_t base,
+                                DeviceState *qdev, const char *name,
+                                target_phys_addr_t size,
                                 BlockDriverState *bs, uint32_t sector_len,
                                 int nb_blocs, int width,
                                 uint16_t id0, uint16_t id1,
-                                uint16_t id2, uint16_t id3,
-                                int be)
+                                uint16_t id2, uint16_t id3, int be)
 {
     pflash_t *pfl;
     target_phys_addr_t total_len;
@@ -596,30 +587,23 @@ pflash_t *pflash_cfi01_register(target_phys_addr_t base, ram_addr_t off,
 
     pfl = g_malloc0(sizeof(pflash_t));
 
-    /* FIXME: Allocate ram ourselves.  */
-    pfl->storage = qemu_get_ram_ptr(off);
-    if (be) {
-        pfl->fl_mem = cpu_register_io_memory(pflash_read_ops_be,
-                                             pflash_write_ops_be, pfl,
-                                             DEVICE_NATIVE_ENDIAN);
-    } else {
-        pfl->fl_mem = cpu_register_io_memory(pflash_read_ops_le,
-                                             pflash_write_ops_le, pfl,
-                                             DEVICE_NATIVE_ENDIAN);
-    }
-    pfl->off = off;
-    cpu_register_physical_memory(base, total_len,
-                    off | pfl->fl_mem | IO_MEM_ROMD);
+    memory_region_init_rom_device(
+        &pfl->mem, be ? &pflash_cfi01_ops_be : &pflash_cfi01_ops_le, pfl,
+        qdev, name, size);
+    pfl->storage = memory_region_get_ram_ptr(&pfl->mem);
+    memory_region_add_subregion(get_system_memory(), base, &pfl->mem);
 
     pfl->bs = bs;
     if (pfl->bs) {
         /* read the initial flash content */
         ret = bdrv_read(pfl->bs, 0, pfl->storage, total_len >> 9);
         if (ret < 0) {
-            cpu_unregister_io_memory(pfl->fl_mem);
+            memory_region_del_subregion(get_system_memory(), &pfl->mem);
+            memory_region_destroy(&pfl->mem);
             g_free(pfl);
             return NULL;
         }
+        bdrv_attach_dev_nofail(pfl->bs, pfl);
     }
 #if 0 /* XXX: there should be a bit to set up read-only,
        *      the same way the hardware does (with WP pin).
@@ -724,3 +708,8 @@ pflash_t *pflash_cfi01_register(target_phys_addr_t base, ram_addr_t off,
 
     return pfl;
 }
+
+MemoryRegion *pflash_cfi01_get_memory(pflash_t *fl)
+{
+    return &fl->mem;
+}
diff --git a/hw/pflash_cfi02.c b/hw/pflash_cfi02.c
index ac5115e4c8..e5a63da595 100644
--- a/hw/pflash_cfi02.c
+++ b/hw/pflash_cfi02.c
@@ -39,6 +39,7 @@
 #include "flash.h"
 #include "qemu-timer.h"
 #include "block.h"
+#include "exec-memory.h"
 
 //#define PFLASH_DEBUG
 #ifdef PFLASH_DEBUG
@@ -69,25 +70,38 @@ struct pflash_t {
     uint8_t cfi_len;
     uint8_t cfi_table[0x52];
     QEMUTimer *timer;
-    ram_addr_t off;
-    int fl_mem;
+    /* The device replicates the flash memory across its memory space.  Emulate
+     * that by having a container (.mem) filled with an array of aliases
+     * (.mem_mappings) pointing to the flash memory (.orig_mem).
+     */
+    MemoryRegion mem;
+    MemoryRegion *mem_mappings;    /* array; one per mapping */
+    MemoryRegion orig_mem;
     int rom_mode;
     int read_counter; /* used for lazy switch-back to rom mode */
     void *storage;
 };
 
-static void pflash_register_memory(pflash_t *pfl, int rom_mode)
+/*
+ * Set up replicated mappings of the same region.
+ */
+static void pflash_setup_mappings(pflash_t *pfl)
 {
-    unsigned long phys_offset = pfl->fl_mem;
-    int i;
-
-    if (rom_mode)
-        phys_offset |= pfl->off | IO_MEM_ROMD;
-    pfl->rom_mode = rom_mode;
+    unsigned i;
+    target_phys_addr_t size = memory_region_size(&pfl->orig_mem);
+
+    memory_region_init(&pfl->mem, "pflash", pfl->mappings * size);
+    pfl->mem_mappings = g_new(MemoryRegion, pfl->mappings);
+    for (i = 0; i < pfl->mappings; ++i) {
+        memory_region_init_alias(&pfl->mem_mappings[i], "pflash-alias",
+                                 &pfl->orig_mem, 0, size);
+        memory_region_add_subregion(&pfl->mem, i * size, &pfl->mem_mappings[i]);
+    }
+}
 
-    for (i = 0; i < pfl->mappings; i++)
-        cpu_register_physical_memory(pfl->base + i * pfl->chip_len,
-                                     pfl->chip_len, phys_offset);
+static void pflash_register_memory(pflash_t *pfl, int rom_mode)
+{
+    memory_region_rom_device_set_readable(&pfl->orig_mem, rom_mode);
 }
 
 static void pflash_timer (void *opaque)
@@ -538,28 +552,20 @@ static void pflash_writel_le(void *opaque, target_phys_addr_t addr,
     pflash_write(pfl, addr, value, 4, 0);
 }
 
-static CPUWriteMemoryFunc * const pflash_write_ops_be[] = {
-    &pflash_writeb_be,
-    &pflash_writew_be,
-    &pflash_writel_be,
-};
-
-static CPUReadMemoryFunc * const pflash_read_ops_be[] = {
-    &pflash_readb_be,
-    &pflash_readw_be,
-    &pflash_readl_be,
+static const MemoryRegionOps pflash_cfi02_ops_be = {
+    .old_mmio = {
+        .read = { pflash_readb_be, pflash_readw_be, pflash_readl_be, },
+        .write = { pflash_writeb_be, pflash_writew_be, pflash_writel_be, },
+    },
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
-static CPUWriteMemoryFunc * const pflash_write_ops_le[] = {
-    &pflash_writeb_le,
-    &pflash_writew_le,
-    &pflash_writel_le,
-};
-
-static CPUReadMemoryFunc * const pflash_read_ops_le[] = {
-    &pflash_readb_le,
-    &pflash_readw_le,
-    &pflash_readl_le,
+static const MemoryRegionOps pflash_cfi02_ops_le = {
+    .old_mmio = {
+        .read = { pflash_readb_le, pflash_readw_le, pflash_readl_le, },
+        .write = { pflash_writeb_le, pflash_writew_le, pflash_writel_le, },
+    },
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 /* Count trailing zeroes of a 32 bits quantity */
@@ -598,7 +604,9 @@ static int ctz32 (uint32_t n)
     return ret;
 }
 
-pflash_t *pflash_cfi02_register(target_phys_addr_t base, ram_addr_t off,
+pflash_t *pflash_cfi02_register(target_phys_addr_t base,
+                                DeviceState *qdev, const char *name,
+                                target_phys_addr_t size,
                                 BlockDriverState *bs, uint32_t sector_len,
                                 int nb_blocs, int nb_mappings, int width,
                                 uint16_t id0, uint16_t id1,
@@ -618,32 +626,26 @@ pflash_t *pflash_cfi02_register(target_phys_addr_t base, ram_addr_t off,
         return NULL;
 #endif
     pfl = g_malloc0(sizeof(pflash_t));
-    /* FIXME: Allocate ram ourselves.  */
-    pfl->storage = qemu_get_ram_ptr(off);
-    if (be) {
-        pfl->fl_mem = cpu_register_io_memory(pflash_read_ops_be,
-                                             pflash_write_ops_be,
-                                             pfl, DEVICE_NATIVE_ENDIAN);
-    } else {
-        pfl->fl_mem = cpu_register_io_memory(pflash_read_ops_le,
-                                             pflash_write_ops_le,
-                                             pfl, DEVICE_NATIVE_ENDIAN);
-    }
-    pfl->off = off;
+    memory_region_init_rom_device(
+        &pfl->orig_mem, be ? &pflash_cfi02_ops_be : &pflash_cfi02_ops_le, pfl,
+        qdev, name, size);
+    pfl->storage = memory_region_get_ram_ptr(&pfl->orig_mem);
     pfl->base = base;
     pfl->chip_len = chip_len;
     pfl->mappings = nb_mappings;
-    pflash_register_memory(pfl, 1);
     pfl->bs = bs;
     if (pfl->bs) {
         /* read the initial flash content */
         ret = bdrv_read(pfl->bs, 0, pfl->storage, chip_len >> 9);
         if (ret < 0) {
-            cpu_unregister_io_memory(pfl->fl_mem);
             g_free(pfl);
             return NULL;
         }
+        bdrv_attach_dev_nofail(pfl->bs, pfl);
     }
+    pflash_setup_mappings(pfl);
+    pfl->rom_mode = 1;
+    memory_region_add_subregion(get_system_memory(), pfl->base, &pfl->mem);
 #if 0 /* XXX: there should be a bit to set up read-only,
        *      the same way the hardware does (with WP pin).
        */
diff --git a/hw/piix_pci.c b/hw/piix_pci.c
index c563c6e1a3..8f6ea42e2c 100644
--- a/hw/piix_pci.c
+++ b/hw/piix_pci.c
@@ -142,6 +142,7 @@ static void i440fx_update_memory_mappings(PCII440FXState *d)
     int i, r;
     uint32_t smram;
 
+    memory_region_transaction_begin();
     update_pam(d, 0xf0000, 0x100000, (d->dev.config[I440FX_PAM] >> 4) & 3,
                &d->pam_regions[0]);
     for(i = 0; i < 12; i++) {
@@ -162,6 +163,7 @@ static void i440fx_update_memory_mappings(PCII440FXState *d)
             d->smram_enabled = false;
         }
     }
+    memory_region_transaction_commit();
 }
 
 static void i440fx_set_smm(int val, void *arg)
@@ -235,9 +237,16 @@ static int i440fx_pcihost_initfn(SysBusDevice *dev)
 {
     I440FXState *s = FROM_SYSBUS(I440FXState, dev);
 
-    pci_host_conf_register_ioport(0xcf8, s);
+    memory_region_init_io(&s->conf_mem, &pci_host_conf_le_ops, s,
+                          "pci-conf-idx", 4);
+    sysbus_add_io(dev, 0xcf8, &s->conf_mem);
+    sysbus_init_ioports(&s->busdev, 0xcf8, 4);
+
+    memory_region_init_io(&s->data_mem, &pci_host_data_le_ops, s,
+                          "pci-conf-data", 4);
+    sysbus_add_io(dev, 0xcfc, &s->data_mem);
+    sysbus_init_ioports(&s->busdev, 0xcfc, 4);
 
-    pci_host_data_register_ioport(0xcfc, s);
     return 0;
 }
 
diff --git a/hw/ppc405_boards.c b/hw/ppc405_boards.c
index dec165e40f..e6c8ac67d9 100644
--- a/hw/ppc405_boards.c
+++ b/hw/ppc405_boards.c
@@ -32,6 +32,7 @@
 #include "qemu-log.h"
 #include "loader.h"
 #include "blockdev.h"
+#include "exec-memory.h"
 
 #define BIOS_FILENAME "ppc405_rom.bin"
 #define BIOS_SIZE (2048 * 1024)
@@ -181,7 +182,8 @@ static void ref405ep_init (ram_addr_t ram_size,
     ppc4xx_bd_info_t bd;
     CPUPPCState *env;
     qemu_irq *pic;
-    ram_addr_t sram_offset, bios_offset, bdloc;
+    MemoryRegion *bios;
+    ram_addr_t sram_offset, bdloc;
     MemoryRegion *ram_memories = g_malloc(2 * sizeof(*ram_memories));
     target_phys_addr_t ram_bases[2], ram_sizes[2];
     target_ulong sram_size;
@@ -224,15 +226,15 @@ static void ref405ep_init (ram_addr_t ram_size,
     dinfo = drive_get(IF_PFLASH, 0, fl_idx);
     if (dinfo) {
         bios_size = bdrv_getlength(dinfo->bdrv);
-        bios_offset = qemu_ram_alloc(NULL, "ef405ep.bios", bios_size);
         fl_sectors = (bios_size + 65535) >> 16;
 #ifdef DEBUG_BOARD_INIT
         printf("Register parallel flash %d size %lx"
-               " at offset %08lx addr %lx '%s' %d\n",
-               fl_idx, bios_size, bios_offset, -bios_size,
+               " at addr %lx '%s' %d\n",
+               fl_idx, bios_size, -bios_size,
                bdrv_get_device_name(dinfo->bdrv), fl_sectors);
 #endif
-        pflash_cfi02_register((uint32_t)(-bios_size), bios_offset,
+        pflash_cfi02_register((uint32_t)(-bios_size),
+                              NULL, "ef405ep.bios", bios_size,
                               dinfo->bdrv, 65536, fl_sectors, 1,
                               2, 0x0001, 0x22DA, 0x0000, 0x0000, 0x555, 0x2AA,
                               1);
@@ -243,12 +245,13 @@ static void ref405ep_init (ram_addr_t ram_size,
 #ifdef DEBUG_BOARD_INIT
         printf("Load BIOS from file\n");
 #endif
-        bios_offset = qemu_ram_alloc(NULL, "ef405ep.bios", BIOS_SIZE);
+        bios = g_new(MemoryRegion, 1);
+        memory_region_init_ram(bios, NULL, "ef405ep.bios", BIOS_SIZE);
         if (bios_name == NULL)
             bios_name = BIOS_FILENAME;
         filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
         if (filename) {
-            bios_size = load_image(filename, qemu_get_ram_ptr(bios_offset));
+            bios_size = load_image(filename, memory_region_get_ram_ptr(bios));
             g_free(filename);
         } else {
             bios_size = -1;
@@ -259,8 +262,9 @@ static void ref405ep_init (ram_addr_t ram_size,
             exit(1);
         }
         bios_size = (bios_size + 0xfff) & ~0xfff;
-        cpu_register_physical_memory((uint32_t)(-bios_size),
-                                     bios_size, bios_offset | IO_MEM_ROM);
+        memory_region_set_readonly(bios, true);
+        memory_region_add_subregion(get_system_memory(),
+                                    (uint32_t)(-bios_size), bios);
     }
     /* Register FPGA */
 #ifdef DEBUG_BOARD_INIT
@@ -507,7 +511,7 @@ static void taihu_405ep_init(ram_addr_t ram_size,
 {
     char *filename;
     qemu_irq *pic;
-    ram_addr_t bios_offset;
+    MemoryRegion *bios;
     MemoryRegion *ram_memories = g_malloc(2 * sizeof(*ram_memories));
     target_phys_addr_t ram_bases[2], ram_sizes[2];
     long bios_size;
@@ -544,14 +548,14 @@ static void taihu_405ep_init(ram_addr_t ram_size,
         /* XXX: should check that size is 2MB */
         //        bios_size = 2 * 1024 * 1024;
         fl_sectors = (bios_size + 65535) >> 16;
-        bios_offset = qemu_ram_alloc(NULL, "taihu_405ep.bios", bios_size);
 #ifdef DEBUG_BOARD_INIT
         printf("Register parallel flash %d size %lx"
-               " at offset %08lx addr %lx '%s' %d\n",
-               fl_idx, bios_size, bios_offset, -bios_size,
+               " at addr %lx '%s' %d\n",
+               fl_idx, bios_size, -bios_size,
                bdrv_get_device_name(dinfo->bdrv), fl_sectors);
 #endif
-        pflash_cfi02_register((uint32_t)(-bios_size), bios_offset,
+        pflash_cfi02_register((uint32_t)(-bios_size),
+                              NULL, "taihu_405ep.bios", bios_size,
                               dinfo->bdrv, 65536, fl_sectors, 1,
                               4, 0x0001, 0x22DA, 0x0000, 0x0000, 0x555, 0x2AA,
                               1);
@@ -564,10 +568,11 @@ static void taihu_405ep_init(ram_addr_t ram_size,
 #endif
         if (bios_name == NULL)
             bios_name = BIOS_FILENAME;
-        bios_offset = qemu_ram_alloc(NULL, "taihu_405ep.bios", BIOS_SIZE);
+        bios = g_new(MemoryRegion, 1);
+        memory_region_init_ram(bios, NULL, "taihu_405ep.bios", BIOS_SIZE);
         filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
         if (filename) {
-            bios_size = load_image(filename, qemu_get_ram_ptr(bios_offset));
+            bios_size = load_image(filename, memory_region_get_ram_ptr(bios));
             g_free(filename);
         } else {
             bios_size = -1;
@@ -578,8 +583,9 @@ static void taihu_405ep_init(ram_addr_t ram_size,
             exit(1);
         }
         bios_size = (bios_size + 0xfff) & ~0xfff;
-        cpu_register_physical_memory((uint32_t)(-bios_size),
-                                     bios_size, bios_offset | IO_MEM_ROM);
+        memory_region_set_readonly(bios, true);
+        memory_region_add_subregion(get_system_memory(), (uint32_t)(-bios_size),
+                                    bios);
     }
     /* Register Linux flash */
     dinfo = drive_get(IF_PFLASH, 0, fl_idx);
@@ -590,12 +596,11 @@ static void taihu_405ep_init(ram_addr_t ram_size,
         fl_sectors = (bios_size + 65535) >> 16;
 #ifdef DEBUG_BOARD_INIT
         printf("Register parallel flash %d size %lx"
-               " at offset %08lx  addr " TARGET_FMT_lx " '%s'\n",
-               fl_idx, bios_size, bios_offset, (target_ulong)0xfc000000,
+               " at addr " TARGET_FMT_lx " '%s'\n",
+               fl_idx, bios_size, (target_ulong)0xfc000000,
                bdrv_get_device_name(dinfo->bdrv));
 #endif
-        bios_offset = qemu_ram_alloc(NULL, "taihu_405ep.flash", bios_size);
-        pflash_cfi02_register(0xfc000000, bios_offset,
+        pflash_cfi02_register(0xfc000000, NULL, "taihu_405ep.flash", bios_size,
                               dinfo->bdrv, 65536, fl_sectors, 1,
                               4, 0x0001, 0x22DA, 0x0000, 0x0000, 0x555, 0x2AA,
                               1);
diff --git a/hw/ppc4xx_pci.c b/hw/ppc4xx_pci.c
index 52e2663a01..339b38ec7a 100644
--- a/hw/ppc4xx_pci.c
+++ b/hw/ppc4xx_pci.c
@@ -368,10 +368,12 @@ PCIBus *ppc4xx_pci_init(CPUState *env, qemu_irq pci_irqs[4],
     cpu_register_physical_memory(config_space + PCIC0_CFGADDR, 4, index);
 
     /* CFGDATA */
-    index = pci_host_data_register_mmio(&controller->pci_state, 1);
-    if (index < 0)
-        goto free;
-    cpu_register_physical_memory(config_space + PCIC0_CFGDATA, 4, index);
+    memory_region_init_io(&controller->pci_state.data_mem,
+                          &pci_host_data_be_ops,
+                          &controller->pci_state, "pci-conf-data", 4);
+    memory_region_add_subregion(get_system_memory(),
+                                config_space + PCIC0_CFGDATA,
+                                &controller->pci_state.data_mem);
 
     /* Internal registers */
     index = cpu_register_io_memory(pci_reg_read, pci_reg_write, controller,
diff --git a/hw/ppce500_pci.c b/hw/ppce500_pci.c
index 4390aeb559..2db365d0b6 100644
--- a/hw/ppce500_pci.c
+++ b/hw/ppce500_pci.c
@@ -79,8 +79,6 @@ struct PPCE500PCIState {
     uint32_t gasket_time;
     qemu_irq irq[4];
     /* mmio maps */
-    int cfgaddr;
-    int cfgdata;
     int reg;
 };
 
@@ -268,18 +266,18 @@ static void e500_pci_map(SysBusDevice *dev, target_phys_addr_t base)
     PCIHostState *h = FROM_SYSBUS(PCIHostState, sysbus_from_qdev(dev));
     PPCE500PCIState *s = DO_UPCAST(PPCE500PCIState, pci_state, h);
 
-    cpu_register_physical_memory(base + PCIE500_CFGADDR, 4, s->cfgaddr);
-    cpu_register_physical_memory(base + PCIE500_CFGDATA, 4, s->cfgdata);
+    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);
 }
 
 static void e500_pci_unmap(SysBusDevice *dev, target_phys_addr_t base)
 {
-    cpu_register_physical_memory(base + PCIE500_CFGADDR, 4,
-                                 IO_MEM_UNASSIGNED);
-    cpu_register_physical_memory(base + PCIE500_CFGDATA, 4,
-                                 IO_MEM_UNASSIGNED);
+    PCIHostState *h = FROM_SYSBUS(PCIHostState, sysbus_from_qdev(dev));
+
+    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);
 }
@@ -309,9 +307,10 @@ static int e500_pcihost_initfn(SysBusDevice *dev)
 
     pci_create_simple(b, 0, "e500-host-bridge");
 
-    s->cfgaddr = pci_host_conf_register_mmio(&s->pci_state, DEVICE_BIG_ENDIAN);
-    s->cfgdata = pci_host_data_register_mmio(&s->pci_state,
-                                             DEVICE_LITTLE_ENDIAN);
+    memory_region_init_io(&h->conf_mem, &pci_host_conf_be_ops, h,
+                          "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);
     sysbus_init_mmio_cb2(dev, e500_pci_map, e500_pci_unmap);
diff --git a/hw/prep_pci.c b/hw/prep_pci.c
index c36232a808..55e4e25099 100644
--- a/hw/prep_pci.c
+++ b/hw/prep_pci.c
@@ -125,9 +125,15 @@ PCIBus *pci_prep_init(qemu_irq *pic,
                               address_space_io,
                               0, 4);
 
-    pci_host_conf_register_ioport(0xcf8, s);
-
-    pci_host_data_register_ioport(0xcfc, s);
+    memory_region_init_io(&s->conf_mem, &pci_host_conf_be_ops, s,
+                          "pci-conf-idx", 1);
+    memory_region_add_subregion(address_space_io, 0xcf8, &s->conf_mem);
+    sysbus_init_ioports(&s->busdev, 0xcf8, 1);
+
+    memory_region_init_io(&s->conf_mem, &pci_host_data_be_ops, s,
+                          "pci-conf-data", 1);
+    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,
diff --git a/hw/qdev-properties.c b/hw/qdev-properties.c
index 0c0c29212d..7ce95b679c 100644
--- a/hw/qdev-properties.c
+++ b/hw/qdev-properties.c
@@ -312,7 +312,7 @@ static int parse_drive(DeviceState *dev, Property *prop, const char *str)
     bs = bdrv_find(str);
     if (bs == NULL)
         return -ENOENT;
-    if (bdrv_attach(bs, dev) < 0)
+    if (bdrv_attach_dev(bs, dev) < 0)
         return -EEXIST;
     *ptr = bs;
     return 0;
@@ -323,7 +323,7 @@ static void free_drive(DeviceState *dev, Property *prop)
     BlockDriverState **ptr = qdev_get_prop_ptr(dev, prop);
 
     if (*ptr) {
-        bdrv_detach(*ptr, dev);
+        bdrv_detach_dev(*ptr, dev);
         blockdev_auto_del(*ptr);
     }
 }
@@ -678,7 +678,7 @@ int qdev_prop_set_drive(DeviceState *dev, const char *name, BlockDriverState *va
 {
     int res;
 
-    res = bdrv_attach(value, dev);
+    res = bdrv_attach_dev(value, dev);
     if (res < 0) {
         error_report("Can't attach drive %s to %s.%s: %s",
                      bdrv_get_device_name(value),
diff --git a/hw/r2d.c b/hw/r2d.c
index 771f3d0733..b8b0df3bb6 100644
--- a/hw/r2d.c
+++ b/hw/r2d.c
@@ -267,7 +267,7 @@ static void r2d_init(ram_addr_t ram_size,
 
     /* onboard flash memory */
     dinfo = drive_get(IF_PFLASH, 0, 0);
-    pflash_cfi02_register(0x0, qemu_ram_alloc(NULL, "r2d.flash", FLASH_SIZE),
+    pflash_cfi02_register(0x0, NULL, "r2d.flash", FLASH_SIZE,
                           dinfo ? dinfo->bdrv : NULL, (16 * 1024),
                           FLASH_SIZE >> 16,
                           1, 4, 0x0000, 0x0000, 0x0000, 0x0000,
diff --git a/hw/scsi-bus.c b/hw/scsi-bus.c
index 6f0d03958d..160eaee693 100644
--- a/hw/scsi-bus.c
+++ b/hw/scsi-bus.c
@@ -498,6 +498,7 @@ void scsi_req_build_sense(SCSIRequest *req, SCSISense sense)
     memset(req->sense, 0, 18);
     req->sense[0] = 0xf0;
     req->sense[2] = sense.key;
+    req->sense[7] = 10;
     req->sense[12] = sense.asc;
     req->sense[13] = sense.ascq;
     req->sense_len = 18;
@@ -883,7 +884,7 @@ int scsi_build_sense(uint8_t *in_buf, int in_len,
         /* Return fixed format sense buffer */
         buf[0] = 0xf0;
         buf[2] = sense.key;
-        buf[7] = 7;
+        buf[7] = 10;
         buf[12] = sense.asc;
         buf[13] = sense.ascq;
         return MIN(len, 18);
@@ -977,7 +978,7 @@ static const char *scsi_command_name(uint8_t cmd)
         [ LOCATE_16                ] = "LOCATE_16",
         [ WRITE_SAME_16            ] = "WRITE_SAME_16",
         [ ERASE_16                 ] = "ERASE_16",
-        [ SERVICE_ACTION_IN        ] = "SERVICE_ACTION_IN",
+        [ SERVICE_ACTION_IN_16     ] = "SERVICE_ACTION_IN_16",
         [ WRITE_LONG_16            ] = "WRITE_LONG_16",
         [ REPORT_LUNS              ] = "REPORT_LUNS",
         [ BLANK                    ] = "BLANK",
@@ -987,6 +988,7 @@ static const char *scsi_command_name(uint8_t cmd)
         [ LOAD_UNLOAD              ] = "LOAD_UNLOAD",
         [ READ_12                  ] = "READ_12",
         [ WRITE_12                 ] = "WRITE_12",
+        [ SERVICE_ACTION_IN_12     ] = "SERVICE_ACTION_IN_12",
         [ WRITE_VERIFY_12          ] = "WRITE_VERIFY_12",
         [ VERIFY_12                ] = "VERIFY_12",
         [ SEARCH_HIGH_12           ] = "SEARCH_HIGH_12",
diff --git a/hw/scsi-defs.h b/hw/scsi-defs.h
index ea288fab07..bfe93922d4 100644
--- a/hw/scsi-defs.h
+++ b/hw/scsi-defs.h
@@ -102,7 +102,7 @@
 #define LOCATE_16             0x92
 #define WRITE_SAME_16         0x93
 #define ERASE_16              0x93
-#define SERVICE_ACTION_IN     0x9e
+#define SERVICE_ACTION_IN_16  0x9e
 #define WRITE_LONG_16         0x9f
 #define REPORT_LUNS           0xa0
 #define BLANK                 0xa1
@@ -112,6 +112,7 @@
 #define LOAD_UNLOAD           0xa6
 #define READ_12               0xa8
 #define WRITE_12              0xaa
+#define SERVICE_ACTION_IN_12  0xab
 #define WRITE_VERIFY_12       0xae
 #define VERIFY_12             0xaf
 #define SEARCH_HIGH_12        0xb0
@@ -123,6 +124,11 @@
 #define SET_CD_SPEED          0xbb
 
 /*
+ * SERVICE ACTION IN subcodes
+ */
+#define SAI_READ_CAPACITY_16  0x10
+
+/*
  *  SAM Status codes
  */
 
diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c
index 3cc830ff95..9724d0fe9a 100644
--- a/hw/scsi-disk.c
+++ b/hw/scsi-disk.c
@@ -111,9 +111,10 @@ static void scsi_read_complete(void * opaque, int ret)
     SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
     int n;
 
-    r->req.aiocb = NULL;
-
-    bdrv_acct_done(s->bs, &r->acct);
+    if (r->req.aiocb != NULL) {
+        r->req.aiocb = NULL;
+        bdrv_acct_done(s->bs, &r->acct);
+    }
 
     if (ret) {
         if (scsi_handle_rw_error(r, -ret, SCSI_REQ_STATUS_RETRY_READ)) {
@@ -129,6 +130,24 @@ static void scsi_read_complete(void * opaque, int ret)
     scsi_req_data(&r->req, r->iov.iov_len);
 }
 
+static void scsi_flush_complete(void * opaque, int ret)
+{
+    SCSIDiskReq *r = (SCSIDiskReq *)opaque;
+    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
+
+    if (r->req.aiocb != NULL) {
+        r->req.aiocb = NULL;
+        bdrv_acct_done(s->bs, &r->acct);
+    }
+
+    if (ret < 0) {
+        if (scsi_handle_rw_error(r, -ret, SCSI_REQ_STATUS_RETRY_FLUSH)) {
+            return;
+        }
+    }
+
+    scsi_req_complete(&r->req, GOOD);
+}
 
 /* Read more data from scsi device into buffer.  */
 static void scsi_read_data(SCSIRequest *req)
@@ -217,9 +236,10 @@ static void scsi_write_complete(void * opaque, int ret)
     uint32_t len;
     uint32_t n;
 
-    r->req.aiocb = NULL;
-
-    bdrv_acct_done(s->bs, &r->acct);
+    if (r->req.aiocb != NULL) {
+        r->req.aiocb = NULL;
+        bdrv_acct_done(s->bs, &r->acct);
+    }
 
     if (ret) {
         if (scsi_handle_rw_error(r, -ret, SCSI_REQ_STATUS_RETRY_WRITE)) {
@@ -526,12 +546,12 @@ static int scsi_disk_emulate_inquiry(SCSIRequest *req, uint8_t *outbuf)
     return buflen;
 }
 
-static int mode_sense_page(SCSIRequest *req, int page, uint8_t *p,
+static int mode_sense_page(SCSIDiskState *s, int page, uint8_t **p_outbuf,
                            int page_control)
 {
-    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev);
     BlockDriverState *bdrv = s->bs;
     int cylinders, heads, secs;
+    uint8_t *p = *p_outbuf;
 
     /*
      * If Changeable Values are requested, a mask denoting those mode parameters
@@ -541,10 +561,13 @@ static int mode_sense_page(SCSIRequest *req, int page, uint8_t *p,
      */
     switch (page) {
     case 4: /* Rigid disk device geometry page. */
+        if (s->qdev.type == TYPE_ROM) {
+            return -1;
+        }
         p[0] = 4;
         p[1] = 0x16;
         if (page_control == 1) { /* Changeable Values */
-            return p[1] + 2;
+            break;
         }
         /* if a geometry hint is available, use it */
         bdrv_get_geometry_hint(bdrv, &cylinders, &heads, &secs);
@@ -570,13 +593,16 @@ static int mode_sense_page(SCSIRequest *req, int page, uint8_t *p,
         /* Medium rotation rate [rpm], 5400 rpm */
         p[20] = (5400 >> 8) & 0xff;
         p[21] = 5400 & 0xff;
-        return p[1] + 2;
+        break;
 
     case 5: /* Flexible disk device geometry page. */
+        if (s->qdev.type == TYPE_ROM) {
+            return -1;
+        }
         p[0] = 5;
         p[1] = 0x1e;
         if (page_control == 1) { /* Changeable Values */
-            return p[1] + 2;
+            break;
         }
         /* Transfer rate [kbit/s], 5Mbit/s */
         p[2] = 5000 >> 8;
@@ -609,26 +635,27 @@ static int mode_sense_page(SCSIRequest *req, int page, uint8_t *p,
         /* Medium rotation rate [rpm], 5400 rpm */
         p[28] = (5400 >> 8) & 0xff;
         p[29] = 5400 & 0xff;
-        return p[1] + 2;
+        break;
 
     case 8: /* Caching page.  */
         p[0] = 8;
         p[1] = 0x12;
         if (page_control == 1) { /* Changeable Values */
-            return p[1] + 2;
+            break;
         }
         if (bdrv_enable_write_cache(s->bs)) {
             p[2] = 4; /* WCE */
         }
-        return p[1] + 2;
+        break;
 
     case 0x2a: /* CD Capabilities and Mechanical Status page. */
-        if (s->qdev.type != TYPE_ROM)
-            return 0;
+        if (s->qdev.type != TYPE_ROM) {
+            return -1;
+        }
         p[0] = 0x2a;
         p[1] = 0x14;
         if (page_control == 1) { /* Changeable Values */
-            return p[1] + 2;
+            break;
         }
         p[2] = 3; // CD-R & CD-RW read
         p[3] = 0; // Writing not supported
@@ -653,27 +680,30 @@ static int mode_sense_page(SCSIRequest *req, int page, uint8_t *p,
         p[19] = (16 * 176) & 0xff;
         p[20] = (16 * 176) >> 8; // 16x write speed current
         p[21] = (16 * 176) & 0xff;
-        return p[1] + 2;
+        break;
 
     default:
-        return 0;
+        return -1;
     }
+
+    *p_outbuf += p[1] + 2;
+    return p[1] + 2;
 }
 
-static int scsi_disk_emulate_mode_sense(SCSIRequest *req, uint8_t *outbuf)
+static int scsi_disk_emulate_mode_sense(SCSIDiskReq *r, uint8_t *outbuf)
 {
-    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev);
+    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
     uint64_t nb_sectors;
-    int page, dbd, buflen, page_control;
+    int page, dbd, buflen, ret, page_control;
     uint8_t *p;
     uint8_t dev_specific_param;
 
-    dbd = req->cmd.buf[1]  & 0x8;
-    page = req->cmd.buf[2] & 0x3f;
-    page_control = (req->cmd.buf[2] & 0xc0) >> 6;
+    dbd = r->req.cmd.buf[1]  & 0x8;
+    page = r->req.cmd.buf[2] & 0x3f;
+    page_control = (r->req.cmd.buf[2] & 0xc0) >> 6;
     DPRINTF("Mode Sense(%d) (page %d, xfer %zd, page_control %d)\n",
-        (req->cmd.buf[0] == MODE_SENSE) ? 6 : 10, page, req->cmd.xfer, page_control);
-    memset(outbuf, 0, req->cmd.xfer);
+        (r->req.cmd.buf[0] == MODE_SENSE) ? 6 : 10, page, r->req.cmd.xfer, page_control);
+    memset(outbuf, 0, r->req.cmd.xfer);
     p = outbuf;
 
     if (bdrv_is_read_only(s->bs)) {
@@ -682,7 +712,7 @@ static int scsi_disk_emulate_mode_sense(SCSIRequest *req, uint8_t *outbuf)
         dev_specific_param = 0x00;
     }
 
-    if (req->cmd.buf[0] == MODE_SENSE) {
+    if (r->req.cmd.buf[0] == MODE_SENSE) {
         p[1] = 0; /* Default media type.  */
         p[2] = dev_specific_param;
         p[3] = 0; /* Block descriptor length.  */
@@ -696,7 +726,7 @@ static int scsi_disk_emulate_mode_sense(SCSIRequest *req, uint8_t *outbuf)
 
     bdrv_get_geometry(s->bs, &nb_sectors);
     if (!dbd && nb_sectors) {
-        if (req->cmd.buf[0] == MODE_SENSE) {
+        if (r->req.cmd.buf[0] == MODE_SENSE) {
             outbuf[3] = 8; /* Block descriptor length  */
         } else { /* MODE_SENSE_10 */
             outbuf[7] = 8; /* Block descriptor length  */
@@ -715,23 +745,21 @@ static int scsi_disk_emulate_mode_sense(SCSIRequest *req, uint8_t *outbuf)
         p += 8;
     }
 
-    if (page_control == 3) { /* Saved Values */
-        return -1; /* ILLEGAL_REQUEST */
+    if (page_control == 3) {
+        /* Saved Values */
+        scsi_check_condition(r, SENSE_CODE(SAVING_PARAMS_NOT_SUPPORTED));
+        return -1;
     }
 
-    switch (page) {
-    case 0x04:
-    case 0x05:
-    case 0x08:
-    case 0x2a:
-        p += mode_sense_page(req, page, p, page_control);
-        break;
-    case 0x3f:
-        p += mode_sense_page(req, 0x08, p, page_control);
-        p += mode_sense_page(req, 0x2a, p, page_control);
-        break;
-    default:
-        return -1; /* ILLEGAL_REQUEST */
+    if (page == 0x3f) {
+        for (page = 0; page <= 0x3e; page++) {
+            mode_sense_page(s, page, &p, page_control);
+        }
+    } else {
+        ret = mode_sense_page(s, page, &p, page_control);
+        if (ret == -1) {
+            return -1;
+        }
     }
 
     buflen = p - outbuf;
@@ -740,14 +768,14 @@ static int scsi_disk_emulate_mode_sense(SCSIRequest *req, uint8_t *outbuf)
      * following data that is available to be transferred. The mode data
      * length does not include itself.
      */
-    if (req->cmd.buf[0] == MODE_SENSE) {
+    if (r->req.cmd.buf[0] == MODE_SENSE) {
         outbuf[0] = buflen - 1;
     } else { /* MODE_SENSE_10 */
         outbuf[0] = ((buflen - 2) >> 8) & 0xff;
         outbuf[1] = (buflen - 2) & 0xff;
     }
-    if (buflen > req->cmd.xfer)
-        buflen = req->cmd.xfer;
+    if (buflen > r->req.cmd.xfer)
+        buflen = r->req.cmd.xfer;
     return buflen;
 }
 
@@ -792,7 +820,6 @@ static int scsi_disk_emulate_command(SCSIDiskReq *r, uint8_t *outbuf)
     SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev);
     uint64_t nb_sectors;
     int buflen = 0;
-    int ret;
 
     switch (req->cmd.buf[0]) {
     case TEST_UNIT_READY:
@@ -806,7 +833,7 @@ static int scsi_disk_emulate_command(SCSIDiskReq *r, uint8_t *outbuf)
         break;
     case MODE_SENSE:
     case MODE_SENSE_10:
-        buflen = scsi_disk_emulate_mode_sense(req, outbuf);
+        buflen = scsi_disk_emulate_mode_sense(r, outbuf);
         if (buflen < 0)
             goto illegal_request;
         break;
@@ -864,20 +891,6 @@ static int scsi_disk_emulate_command(SCSIDiskReq *r, uint8_t *outbuf)
         outbuf[7] = 0;
         buflen = 8;
         break;
-    case SYNCHRONIZE_CACHE:
-    {
-        BlockAcctCookie acct;
-
-        bdrv_acct_start(s->bs, &acct, 0, BDRV_ACCT_FLUSH);
-        ret = bdrv_flush(s->bs);
-        bdrv_acct_done(s->bs, &acct);
-        if (ret < 0) {
-            if (scsi_handle_rw_error(r, -ret, SCSI_REQ_STATUS_RETRY_FLUSH)) {
-                return -1;
-            }
-        }
-        break;
-    }
     case GET_CONFIGURATION:
         memset(outbuf, 0, 8);
         /* ??? This should probably return much more information.  For now
@@ -885,9 +898,9 @@ static int scsi_disk_emulate_command(SCSIDiskReq *r, uint8_t *outbuf)
         outbuf[7] = 8; // CD-ROM
         buflen = 8;
         break;
-    case SERVICE_ACTION_IN:
+    case SERVICE_ACTION_IN_16:
         /* Service Action In subcommands. */
-        if ((req->cmd.buf[1] & 31) == 0x10) {
+        if ((req->cmd.buf[1] & 31) == SAI_READ_CAPACITY_16) {
             DPRINTF("SAI READ CAPACITY(16)\n");
             memset(outbuf, 0, req->cmd.xfer);
             bdrv_get_geometry(s->bs, &nb_sectors);
@@ -941,7 +954,9 @@ not_ready:
     return -1;
 
 illegal_request:
-    scsi_check_condition(r, SENSE_CODE(INVALID_FIELD));
+    if (r->req.status == -1) {
+        scsi_check_condition(r, SENSE_CODE(INVALID_FIELD));
+    }
     return -1;
 }
 
@@ -985,10 +1000,9 @@ static int32_t scsi_send_command(SCSIRequest *req, uint8_t *buf)
     case START_STOP:
     case ALLOW_MEDIUM_REMOVAL:
     case READ_CAPACITY_10:
-    case SYNCHRONIZE_CACHE:
     case READ_TOC:
     case GET_CONFIGURATION:
-    case SERVICE_ACTION_IN:
+    case SERVICE_ACTION_IN_16:
     case VERIFY_10:
         rc = scsi_disk_emulate_command(r, outbuf);
         if (rc < 0) {
@@ -997,6 +1011,13 @@ static int32_t scsi_send_command(SCSIRequest *req, uint8_t *buf)
 
         r->iov.iov_len = rc;
         break;
+    case SYNCHRONIZE_CACHE:
+        bdrv_acct_start(s->bs, &r->acct, 0, BDRV_ACCT_FLUSH);
+        r->req.aiocb = bdrv_aio_flush(s->bs, scsi_flush_complete, r);
+        if (r->req.aiocb == NULL) {
+            scsi_flush_complete(r, -EIO);
+        }
+        return 0;
     case READ_6:
     case READ_10:
     case READ_12:
diff --git a/hw/sd.c b/hw/sd.c
index bb8c2ff677..1af62b23c6 100644
--- a/hw/sd.c
+++ b/hw/sd.c
@@ -31,7 +31,6 @@
 
 #include "hw.h"
 #include "block.h"
-#include "block_int.h"
 #include "sd.h"
 
 //#define DEBUG_SD 1
@@ -420,14 +419,10 @@ static void sd_reset(SDState *sd, BlockDriverState *bdrv)
     sd->pwd_len = 0;
 }
 
-static void sd_cardchange(void *opaque, int reason)
+static void sd_cardchange(void *opaque)
 {
     SDState *sd = opaque;
 
-    if (!(reason & CHANGE_MEDIA)) {
-        return;
-    }
-
     qemu_set_irq(sd->inserted_cb, bdrv_is_inserted(sd->bdrv));
     if (bdrv_is_inserted(sd->bdrv)) {
         sd_reset(sd, sd->bdrv);
@@ -435,6 +430,10 @@ static void sd_cardchange(void *opaque, int reason)
     }
 }
 
+static const BlockDevOps sd_block_ops = {
+    .change_media_cb = sd_cardchange,
+};
+
 /* We do not model the chip select pin, so allow the board to select
    whether card should be in SSI or MMC/SD mode.  It is also up to the
    board to ensure that ssi transfers only occur when the chip select
@@ -449,7 +448,8 @@ SDState *sd_init(BlockDriverState *bs, int is_spi)
     sd->enable = 1;
     sd_reset(sd, bs);
     if (sd->bdrv) {
-        bdrv_set_change_cb(sd->bdrv, sd_cardchange, sd);
+        bdrv_attach_dev_nofail(sd->bdrv, sd);
+        bdrv_set_dev_ops(sd->bdrv, &sd_block_ops, sd);
     }
     return sd;
 }
diff --git a/hw/sh_intc.c b/hw/sh_intc.c
index ecb46e5856..e07424f2a1 100644
--- a/hw/sh_intc.c
+++ b/hw/sh_intc.c
@@ -382,13 +382,14 @@ void sh_intc_register_sources(struct intc_desc *desc,
 
 	sh_intc_register_source(desc, vect->enum_id, groups, nr_groups);
 	s = sh_intc_source(desc, vect->enum_id);
-	if (s)
-	    s->vect = vect->vect;
+        if (s) {
+            s->vect = vect->vect;
 
 #ifdef DEBUG_INTC_SOURCES
-	printf("sh_intc: registered source %d -> 0x%04x (%d/%d)\n",
-	       vect->enum_id, s->vect, s->enable_count, s->enable_max);
+            printf("sh_intc: registered source %d -> 0x%04x (%d/%d)\n",
+                   vect->enum_id, s->vect, s->enable_count, s->enable_max);
 #endif
+        }
     }
 
     if (groups) {
diff --git a/hw/spitz.c b/hw/spitz.c
index c05b5f7d56..0adae596b5 100644
--- a/hw/spitz.c
+++ b/hw/spitz.c
@@ -708,17 +708,13 @@ static void spitz_ssp_attach(PXA2xxState *cpu)
 static void spitz_microdrive_attach(PXA2xxState *cpu, int slot)
 {
     PCMCIACardState *md;
-    BlockDriverState *bs;
     DriveInfo *dinfo;
 
     dinfo = drive_get(IF_IDE, 0, 0);
-    if (!dinfo)
+    if (!dinfo || dinfo->media_cd)
         return;
-    bs = dinfo->bdrv;
-    if (bdrv_is_inserted(bs) && !bdrv_is_removable(bs)) {
-        md = dscm1xxxx_init(dinfo);
-        pxa2xx_pcmcia_attach(cpu->pcmcia[slot], md);
-    }
+    md = dscm1xxxx_init(dinfo);
+    pxa2xx_pcmcia_attach(cpu->pcmcia[slot], md);
 }
 
 /* Wm8750 and Max7310 on I2C */
diff --git a/hw/stellaris.c b/hw/stellaris.c
index 9b0db7f511..2bf1c235dc 100644
--- a/hw/stellaris.c
+++ b/hw/stellaris.c
@@ -15,6 +15,7 @@
 #include "i2c.h"
 #include "net.h"
 #include "boards.h"
+#include "exec-memory.h"
 
 #define GPIO_A 0
 #define GPIO_B 1
@@ -1260,6 +1261,7 @@ static void stellaris_init(const char *kernel_filename, const char *cpu_model,
         0x40024000, 0x40025000, 0x40026000};
     static const int gpio_irq[7] = {0, 1, 2, 3, 4, 30, 31};
 
+    MemoryRegion *address_space_mem = get_system_memory();
     qemu_irq *pic;
     DeviceState *gpio_dev[7];
     qemu_irq gpio_in[7][8];
@@ -1274,7 +1276,8 @@ static void stellaris_init(const char *kernel_filename, const char *cpu_model,
 
     flash_size = ((board->dc0 & 0xffff) + 1) << 1;
     sram_size = (board->dc0 >> 18) + 1;
-    pic = armv7m_init(flash_size, sram_size, kernel_filename, cpu_model);
+    pic = armv7m_init(address_space_mem,
+                      flash_size, sram_size, kernel_filename, cpu_model);
 
     if (board->dc1 & (1 << 16)) {
         dev = sysbus_create_varargs("stellaris-adc", 0x40038000,
diff --git a/hw/stellaris_enet.c b/hw/stellaris_enet.c
index f9bd3da209..d5613ffffd 100644
--- a/hw/stellaris_enet.c
+++ b/hw/stellaris_enet.c
@@ -69,7 +69,7 @@ typedef struct {
     NICState *nic;
     NICConf conf;
     qemu_irq irq;
-    int mmio_index;
+    MemoryRegion mmio;
 } stellaris_enet_state;
 
 static void stellaris_enet_update(stellaris_enet_state *s)
@@ -130,7 +130,8 @@ static int stellaris_enet_can_receive(VLANClientState *nc)
     return (s->np < 31);
 }
 
-static uint32_t stellaris_enet_read(void *opaque, target_phys_addr_t offset)
+static uint64_t stellaris_enet_read(void *opaque, target_phys_addr_t offset,
+                                    unsigned size)
 {
     stellaris_enet_state *s = (stellaris_enet_state *)opaque;
     uint32_t val;
@@ -198,7 +199,7 @@ static uint32_t stellaris_enet_read(void *opaque, target_phys_addr_t offset)
 }
 
 static void stellaris_enet_write(void *opaque, target_phys_addr_t offset,
-                        uint32_t value)
+                                 uint64_t value, unsigned size)
 {
     stellaris_enet_state *s = (stellaris_enet_state *)opaque;
 
@@ -303,17 +304,12 @@ static void stellaris_enet_write(void *opaque, target_phys_addr_t offset,
     }
 }
 
-static CPUReadMemoryFunc * const stellaris_enet_readfn[] = {
-   stellaris_enet_read,
-   stellaris_enet_read,
-   stellaris_enet_read
+static const MemoryRegionOps stellaris_enet_ops = {
+    .read = stellaris_enet_read,
+    .write = stellaris_enet_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
-static CPUWriteMemoryFunc * const stellaris_enet_writefn[] = {
-   stellaris_enet_write,
-   stellaris_enet_write,
-   stellaris_enet_write
-};
 static void stellaris_enet_reset(stellaris_enet_state *s)
 {
     s->mdv = 0x80;
@@ -391,7 +387,7 @@ static void stellaris_enet_cleanup(VLANClientState *nc)
 
     unregister_savevm(&s->busdev.qdev, "stellaris_enet", s);
 
-    cpu_unregister_io_memory(s->mmio_index);
+    memory_region_destroy(&s->mmio);
 
     g_free(s);
 }
@@ -408,10 +404,9 @@ static int stellaris_enet_init(SysBusDevice *dev)
 {
     stellaris_enet_state *s = FROM_SYSBUS(stellaris_enet_state, dev);
 
-    s->mmio_index = cpu_register_io_memory(stellaris_enet_readfn,
-                                           stellaris_enet_writefn, s,
-                                           DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio(dev, 0x1000, s->mmio_index);
+    memory_region_init_io(&s->mmio, &stellaris_enet_ops, s, "stellaris_enet",
+                          0x1000);
+    sysbus_init_mmio_region(dev, &s->mmio);
     sysbus_init_irq(dev, &s->irq);
     qemu_macaddr_default_if_unset(&s->conf.macaddr);
 
diff --git a/hw/sysbus.c b/hw/sysbus.c
index c365d39d24..4fab5a41b2 100644
--- a/hw/sysbus.c
+++ b/hw/sysbus.c
@@ -261,3 +261,32 @@ static char *sysbus_get_fw_dev_path(DeviceState *dev)
 
     return strdup(path);
 }
+
+void sysbus_add_memory(SysBusDevice *dev, target_phys_addr_t addr,
+                       MemoryRegion *mem)
+{
+    memory_region_add_subregion(get_system_memory(), addr, mem);
+}
+
+void sysbus_add_memory_overlap(SysBusDevice *dev, target_phys_addr_t addr,
+                               MemoryRegion *mem, unsigned priority)
+{
+    memory_region_add_subregion_overlap(get_system_memory(), addr, mem,
+                                        priority);
+}
+
+void sysbus_del_memory(SysBusDevice *dev, MemoryRegion *mem)
+{
+    memory_region_del_subregion(get_system_memory(), mem);
+}
+
+void sysbus_add_io(SysBusDevice *dev, target_phys_addr_t addr,
+                       MemoryRegion *mem)
+{
+    memory_region_add_subregion(get_system_io(), addr, mem);
+}
+
+void sysbus_del_io(SysBusDevice *dev, MemoryRegion *mem)
+{
+    memory_region_del_subregion(get_system_io(), mem);
+}
diff --git a/hw/sysbus.h b/hw/sysbus.h
index aa3d383277..6c36537c24 100644
--- a/hw/sysbus.h
+++ b/hw/sysbus.h
@@ -58,6 +58,14 @@ void sysbus_init_ioports(SysBusDevice *dev, pio_addr_t ioport, pio_addr_t size);
 
 void sysbus_connect_irq(SysBusDevice *dev, int n, qemu_irq irq);
 void sysbus_mmio_map(SysBusDevice *dev, int n, target_phys_addr_t addr);
+void sysbus_add_memory(SysBusDevice *dev, target_phys_addr_t addr,
+                       MemoryRegion *mem);
+void sysbus_add_memory_overlap(SysBusDevice *dev, target_phys_addr_t addr,
+                               MemoryRegion *mem, unsigned priority);
+void sysbus_del_memory(SysBusDevice *dev, MemoryRegion *mem);
+void sysbus_add_io(SysBusDevice *dev, target_phys_addr_t addr,
+                   MemoryRegion *mem);
+void sysbus_del_io(SysBusDevice *dev, MemoryRegion *mem);
 
 /* Legacy helper function for creating devices.  */
 DeviceState *sysbus_create_varargs(const char *name,
diff --git a/hw/tosa.c b/hw/tosa.c
index a7967a286e..7b407f4f64 100644
--- a/hw/tosa.c
+++ b/hw/tosa.c
@@ -51,17 +51,13 @@
 static void tosa_microdrive_attach(PXA2xxState *cpu)
 {
     PCMCIACardState *md;
-    BlockDriverState *bs;
     DriveInfo *dinfo;
 
     dinfo = drive_get(IF_IDE, 0, 0);
-    if (!dinfo)
+    if (!dinfo || dinfo->media_cd)
         return;
-    bs = dinfo->bdrv;
-    if (bdrv_is_inserted(bs) && !bdrv_is_removable(bs)) {
-        md = dscm1xxxx_init(dinfo);
-        pxa2xx_pcmcia_attach(cpu->pcmcia[0], md);
-    }
+    md = dscm1xxxx_init(dinfo);
+    pxa2xx_pcmcia_attach(cpu->pcmcia[0], md);
 }
 
 static void tosa_out_switch(void *opaque, int line, int level)
diff --git a/hw/tusb6010.c b/hw/tusb6010.c
index de6ffc6133..ce7c81f8f2 100644
--- a/hw/tusb6010.c
+++ b/hw/tusb6010.c
@@ -771,13 +771,12 @@ static void tusb6010_reset(DeviceState *dev)
     for (i = 0; i < 15; i++) {
         s->rx_config[i] = s->tx_config[i] = 0;
     }
+    musb_reset(s->musb);
 }
 
 static int tusb6010_init(SysBusDevice *dev)
 {
     TUSBState *s = FROM_SYSBUS(TUSBState, dev);
-    qemu_irq *musb_irqs;
-    int i;
     s->otg_timer = qemu_new_timer_ns(vm_clock, tusb_otg_tick, s);
     s->pwr_timer = qemu_new_timer_ns(vm_clock, tusb_power_tick, s);
     memory_region_init_io(&s->iomem[1], &tusb_async_ops, s, "tusb-async",
@@ -785,12 +784,8 @@ static int tusb6010_init(SysBusDevice *dev)
     sysbus_init_mmio_region(dev, &s->iomem[0]);
     sysbus_init_mmio_region(dev, &s->iomem[1]);
     sysbus_init_irq(dev, &s->irq);
-    qdev_init_gpio_in(&dev->qdev, tusb6010_irq, __musb_irq_max + 1);
-    musb_irqs = g_new0(qemu_irq, __musb_irq_max);
-    for (i = 0; i < __musb_irq_max; i++) {
-        musb_irqs[i] = qdev_get_gpio_in(&dev->qdev, i + 1);
-    }
-    s->musb = musb_init(musb_irqs);
+    qdev_init_gpio_in(&dev->qdev, tusb6010_irq, musb_irq_max + 1);
+    s->musb = musb_init(&dev->qdev, 1);
     return 0;
 }
 
diff --git a/hw/unin_pci.c b/hw/unin_pci.c
index f896f8c76b..600cd1e5bd 100644
--- a/hw/unin_pci.c
+++ b/hw/unin_pci.c
@@ -41,7 +41,6 @@ static const int unin_irq_line[] = { 0x1b, 0x1c, 0x1d, 0x1e };
 typedef struct UNINState {
     SysBusDevice busdev;
     PCIHostState host_state;
-    ReadWriteHandler data_handler;
 } UNINState;
 
 static int pci_unin_map_irq(PCIDevice *pci_dev, int irq_num)
@@ -100,67 +99,70 @@ static uint32_t unin_get_config_reg(uint32_t reg, uint32_t addr)
     return retval;
 }
 
-static void unin_data_write(ReadWriteHandler *handler,
-                            pcibus_t addr, uint32_t val, int len)
+static void unin_data_write(void *opaque, target_phys_addr_t addr,
+                            uint64_t val, unsigned len)
 {
-    UNINState *s = container_of(handler, UNINState, data_handler);
-    UNIN_DPRINTF("write addr %" FMT_PCIBUS " len %d val %x\n", addr, len, val);
+    UNINState *s = opaque;
+    UNIN_DPRINTF("write addr %" TARGET_FMT_plx " len %d val %"PRIx64"\n",
+                 addr, len, val);
     pci_data_write(s->host_state.bus,
                    unin_get_config_reg(s->host_state.config_reg, addr),
                    val, len);
 }
 
-static uint32_t unin_data_read(ReadWriteHandler *handler,
-                               pcibus_t addr, int len)
+static uint64_t unin_data_read(void *opaque, target_phys_addr_t addr,
+                               unsigned len)
 {
-    UNINState *s = container_of(handler, UNINState, data_handler);
+    UNINState *s = opaque;
     uint32_t val;
 
     val = pci_data_read(s->host_state.bus,
                         unin_get_config_reg(s->host_state.config_reg, addr),
                         len);
-    UNIN_DPRINTF("read addr %" FMT_PCIBUS " len %d val %x\n", addr, len, val);
+    UNIN_DPRINTF("read addr %" TARGET_FMT_plx " len %d val %x\n",
+                 addr, len, val);
     return val;
 }
 
+static const MemoryRegionOps unin_data_ops = {
+    .read = unin_data_read,
+    .write = unin_data_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+};
+
 static int pci_unin_main_init_device(SysBusDevice *dev)
 {
     UNINState *s;
-    int pci_mem_config, pci_mem_data;
 
     /* Use values found on a real PowerMac */
     /* Uninorth main bus */
     s = FROM_SYSBUS(UNINState, dev);
 
-    pci_mem_config = pci_host_conf_register_mmio(&s->host_state,
-                                                 DEVICE_LITTLE_ENDIAN);
-    s->data_handler.read = unin_data_read;
-    s->data_handler.write = unin_data_write;
-    pci_mem_data = cpu_register_io_memory_simple(&s->data_handler,
-                                                 DEVICE_LITTLE_ENDIAN);
-    sysbus_init_mmio(dev, 0x1000, pci_mem_config);
-    sysbus_init_mmio(dev, 0x1000, pci_mem_data);
+    memory_region_init_io(&s->host_state.conf_mem, &pci_host_conf_le_ops,
+                          &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);
 
     qemu_register_reset(pci_unin_reset, &s->host_state);
     return 0;
 }
 
+
 static int pci_u3_agp_init_device(SysBusDevice *dev)
 {
     UNINState *s;
-    int pci_mem_config, pci_mem_data;
 
     /* Uninorth U3 AGP bus */
     s = FROM_SYSBUS(UNINState, dev);
 
-    pci_mem_config = pci_host_conf_register_mmio(&s->host_state,
-                                                 DEVICE_LITTLE_ENDIAN);
-    s->data_handler.read = unin_data_read;
-    s->data_handler.write = unin_data_write;
-    pci_mem_data = cpu_register_io_memory_simple(&s->data_handler,
-                                                 DEVICE_LITTLE_ENDIAN);
-    sysbus_init_mmio(dev, 0x1000, pci_mem_config);
-    sysbus_init_mmio(dev, 0x1000, pci_mem_data);
+    memory_region_init_io(&s->host_state.conf_mem, &pci_host_conf_le_ops,
+                          &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);
 
     qemu_register_reset(pci_unin_reset, &s->host_state);
 
@@ -170,34 +172,32 @@ static int pci_u3_agp_init_device(SysBusDevice *dev)
 static int pci_unin_agp_init_device(SysBusDevice *dev)
 {
     UNINState *s;
-    int pci_mem_config, pci_mem_data;
 
     /* Uninorth AGP bus */
     s = FROM_SYSBUS(UNINState, dev);
 
-    pci_mem_config = pci_host_conf_register_mmio(&s->host_state,
-                                                 DEVICE_LITTLE_ENDIAN);
-    pci_mem_data = pci_host_data_register_mmio(&s->host_state,
-                                               DEVICE_LITTLE_ENDIAN);
-    sysbus_init_mmio(dev, 0x1000, pci_mem_config);
-    sysbus_init_mmio(dev, 0x1000, pci_mem_data);
+    memory_region_init_io(&s->host_state.conf_mem, &pci_host_conf_le_ops,
+                          &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);
     return 0;
 }
 
 static int pci_unin_internal_init_device(SysBusDevice *dev)
 {
     UNINState *s;
-    int pci_mem_config, pci_mem_data;
 
     /* Uninorth internal bus */
     s = FROM_SYSBUS(UNINState, dev);
 
-    pci_mem_config = pci_host_conf_register_mmio(&s->host_state,
-                                                 DEVICE_LITTLE_ENDIAN);
-    pci_mem_data = pci_host_data_register_mmio(&s->host_state,
-                                               DEVICE_LITTLE_ENDIAN);
-    sysbus_init_mmio(dev, 0x1000, pci_mem_config);
-    sysbus_init_mmio(dev, 0x1000, pci_mem_data);
+    memory_region_init_io(&s->host_state.conf_mem, &pci_host_conf_le_ops,
+                          &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);
     return 0;
 }
 
diff --git a/hw/usb-bus.c b/hw/usb-bus.c
index c0bbc7c6b0..93f640d370 100644
--- a/hw/usb-bus.c
+++ b/hw/usb-bus.c
@@ -3,6 +3,7 @@
 #include "qdev.h"
 #include "sysemu.h"
 #include "monitor.h"
+#include "trace.h"
 
 static void usb_bus_dev_print(Monitor *mon, DeviceState *qdev, int indent);
 
@@ -73,9 +74,13 @@ static int usb_qdev_init(DeviceState *qdev, DeviceInfo *base)
     dev->info = info;
     dev->auto_attach = 1;
     QLIST_INIT(&dev->strings);
-    rc = dev->info->init(dev);
-    if (rc == 0 && dev->auto_attach)
+    rc = usb_claim_port(dev);
+    if (rc == 0) {
+        rc = dev->info->init(dev);
+    }
+    if (rc == 0 && dev->auto_attach) {
         rc = usb_device_attach(dev);
+    }
     return rc;
 }
 
@@ -89,6 +94,9 @@ static int usb_qdev_exit(DeviceState *qdev)
     if (dev->info->handle_destroy) {
         dev->info->handle_destroy(dev);
     }
+    if (dev->port) {
+        usb_release_port(dev);
+    }
     return 0;
 }
 
@@ -205,21 +213,13 @@ void usb_unregister_port(USBBus *bus, USBPort *port)
     bus->nfree--;
 }
 
-static int do_attach(USBDevice *dev)
+int usb_claim_port(USBDevice *dev)
 {
     USBBus *bus = usb_bus_from_device(dev);
     USBPort *port;
 
-    if (dev->attached) {
-        error_report("Error: tried to attach usb device %s twice\n",
-                dev->product_desc);
-        return -1;
-    }
-    if (bus->nfree == 0) {
-        error_report("Error: tried to attach usb device %s to a bus with no free ports\n",
-                dev->product_desc);
-        return -1;
-    }
+    assert(dev->port == NULL);
+
     if (dev->port_path) {
         QTAILQ_FOREACH(port, &bus->free, next) {
             if (strcmp(port->path, dev->port_path) == 0) {
@@ -227,68 +227,86 @@ static int do_attach(USBDevice *dev)
             }
         }
         if (port == NULL) {
-            error_report("Error: usb port %s (bus %s) not found\n",
-                    dev->port_path, bus->qbus.name);
+            error_report("Error: usb port %s (bus %s) not found (in use?)\n",
+                         dev->port_path, bus->qbus.name);
             return -1;
         }
     } else {
+        if (bus->nfree == 1 && strcmp(dev->qdev.info->name, "usb-hub") != 0) {
+            /* Create a new hub and chain it on */
+            usb_create_simple(bus, "usb-hub");
+        }
+        if (bus->nfree == 0) {
+            error_report("Error: tried to attach usb device %s to a bus "
+                         "with no free ports\n", dev->product_desc);
+            return -1;
+        }
         port = QTAILQ_FIRST(&bus->free);
     }
-    if (!(port->speedmask & dev->speedmask)) {
-        error_report("Warning: speed mismatch trying to attach usb device %s to bus %s\n",
-                dev->product_desc, bus->qbus.name);
-        return -1;
-    }
+    trace_usb_port_claim(bus->busnr, port->path);
 
-    dev->attached++;
     QTAILQ_REMOVE(&bus->free, port, next);
     bus->nfree--;
 
-    usb_attach(port, dev);
+    dev->port = port;
+    port->dev = dev;
 
     QTAILQ_INSERT_TAIL(&bus->used, port, next);
     bus->nused++;
-
     return 0;
 }
 
-int usb_device_attach(USBDevice *dev)
+void usb_release_port(USBDevice *dev)
 {
     USBBus *bus = usb_bus_from_device(dev);
+    USBPort *port = dev->port;
 
-    if (bus->nfree == 1 && dev->port_path == NULL) {
-        /* Create a new hub and chain it on
-           (unless a physical port location is specified). */
-        usb_create_simple(bus, "usb-hub");
-    }
-    return do_attach(dev);
+    assert(port != NULL);
+    trace_usb_port_release(bus->busnr, port->path);
+
+    QTAILQ_REMOVE(&bus->used, port, next);
+    bus->nused--;
+
+    dev->port = NULL;
+    port->dev = NULL;
+
+    QTAILQ_INSERT_TAIL(&bus->free, port, next);
+    bus->nfree++;
 }
 
-int usb_device_detach(USBDevice *dev)
+int usb_device_attach(USBDevice *dev)
 {
     USBBus *bus = usb_bus_from_device(dev);
-    USBPort *port;
+    USBPort *port = dev->port;
 
-    if (!dev->attached) {
-        error_report("Error: tried to detach unattached usb device %s\n",
-                dev->product_desc);
+    assert(port != NULL);
+    assert(!dev->attached);
+    trace_usb_port_attach(bus->busnr, port->path);
+
+    if (!(port->speedmask & dev->speedmask)) {
+        error_report("Warning: speed mismatch trying to attach "
+                     "usb device %s to bus %s\n",
+                     dev->product_desc, bus->qbus.name);
         return -1;
     }
-    dev->attached--;
 
-    QTAILQ_FOREACH(port, &bus->used, next) {
-        if (port->dev == dev)
-            break;
-    }
-    assert(port != NULL);
+    dev->attached++;
+    usb_attach(port);
 
-    QTAILQ_REMOVE(&bus->used, port, next);
-    bus->nused--;
+    return 0;
+}
+
+int usb_device_detach(USBDevice *dev)
+{
+    USBBus *bus = usb_bus_from_device(dev);
+    USBPort *port = dev->port;
 
-    usb_attach(port, NULL);
+    assert(port != NULL);
+    assert(dev->attached);
+    trace_usb_port_detach(bus->busnr, port->path);
 
-    QTAILQ_INSERT_TAIL(&bus->free, port, next);
-    bus->nfree++;
+    usb_detach(port);
+    dev->attached--;
     return 0;
 }
 
diff --git a/hw/usb-ccid.c b/hw/usb-ccid.c
index c2f9241014..cd349f3f17 100644
--- a/hw/usb-ccid.c
+++ b/hw/usb-ccid.c
@@ -37,6 +37,7 @@
 #include "qemu-common.h"
 #include "qemu-error.h"
 #include "usb.h"
+#include "usb-desc.h"
 #include "monitor.h"
 
 #include "hw/ccid.h"
@@ -306,56 +307,7 @@ typedef struct USBCCIDState {
  *   0dc3:1004 Athena Smartcard Solutions, Inc.
  */
 
-static const uint8_t qemu_ccid_dev_descriptor[] = {
-        0x12,       /*  u8 bLength; */
-        USB_DT_DEVICE, /*  u8 bDescriptorType; Device */
-        0x10, 0x01, /*  u16 bcdUSB; v1.1 */
-
-        0x00,       /*  u8  bDeviceClass; */
-        0x00,       /*  u8  bDeviceSubClass; */
-        0x00,       /*  u8  bDeviceProtocol; [ low/full speeds only ] */
-        0x40,       /*  u8  bMaxPacketSize0; 8 Bytes (valid: 8,16,32,64) */
-
-        /* Vendor and product id are arbitrary.  */
-                    /*  u16 idVendor  */
-        CCID_VENDOR_ID & 0xff, CCID_VENDOR_ID >> 8,
-                    /*  u16 idProduct */
-        CCID_PRODUCT_ID & 0xff, CCID_PRODUCT_ID >> 8,
-                    /*  u16 bcdDevice */
-        CCID_DEVICE_VERSION & 0xff, CCID_DEVICE_VERSION >> 8,
-        0x01,       /*  u8  iManufacturer; */
-        0x02,       /*  u8  iProduct; */
-        0x03,       /*  u8  iSerialNumber; */
-        0x01,       /*  u8  bNumConfigurations; */
-};
-
-static const uint8_t qemu_ccid_config_descriptor[] = {
-
-        /* one configuration */
-        0x09,       /* u8  bLength; */
-        USB_DT_CONFIG, /* u8  bDescriptorType; Configuration */
-        0x5d, 0x00, /* u16 wTotalLength; 9+9+54+7+7+7 */
-        0x01,       /* u8  bNumInterfaces; (1) */
-        0x01,       /* u8  bConfigurationValue; */
-        0x00,       /* u8  iConfiguration; */
-        0xe0,       /* u8  bmAttributes;
-                                 Bit 7: must be set,
-                                     6: Self-powered,
-                                     5: Remote wakeup,
-                                     4..0: resvd */
-        100/2,      /* u8  MaxPower; 50 == 100mA */
-
-        /* one interface */
-        0x09,       /* u8  if_bLength; */
-        USB_DT_INTERFACE, /* u8  if_bDescriptorType; Interface */
-        0x00,       /* u8  if_bInterfaceNumber; */
-        0x00,       /* u8  if_bAlternateSetting; */
-        0x03,       /* u8  if_bNumEndpoints; */
-        0x0b,       /* u8  if_bInterfaceClass; Smart Card Device Class */
-        0x00,       /* u8  if_bInterfaceSubClass; Subclass code */
-        0x00,       /* u8  if_bInterfaceProtocol; Protocol code */
-        0x04,       /* u8  if_iInterface; Index of string descriptor */
-
+static const uint8_t qemu_ccid_descriptor[] = {
         /* Smart Card Device Class Descriptor */
         0x36,       /* u8  bLength; */
         0x21,       /* u8  bDescriptorType; Functional */
@@ -439,38 +391,81 @@ static const uint8_t qemu_ccid_config_descriptor[] = {
                      *                  02h PIN Modification
                      */
         0x01,       /* u8  bMaxCCIDBusySlots; */
+};
 
-        /* Interrupt-IN endpoint */
-        0x07,       /* u8  ep_bLength; */
-                    /* u8  ep_bDescriptorType; Endpoint */
-        USB_DT_ENDPOINT,
-                    /* u8  ep_bEndpointAddress; IN Endpoint 1 */
-        0x80 | CCID_INT_IN_EP,
-        0x03,       /* u8  ep_bmAttributes; Interrupt */
-                    /* u16 ep_wMaxPacketSize; */
-        CCID_MAX_PACKET_SIZE & 0xff, (CCID_MAX_PACKET_SIZE >> 8),
-        0xff,       /* u8  ep_bInterval; */
-
-        /* Bulk-In endpoint */
-        0x07,       /* u8  ep_bLength; */
-                    /* u8  ep_bDescriptorType; Endpoint */
-        USB_DT_ENDPOINT,
-                    /* u8  ep_bEndpointAddress; IN Endpoint 2 */
-        0x80 | CCID_BULK_IN_EP,
-        0x02,       /* u8  ep_bmAttributes; Bulk */
-        0x40, 0x00, /* u16 ep_wMaxPacketSize; */
-        0x00,       /* u8  ep_bInterval; */
-
-        /* Bulk-Out endpoint */
-        0x07,       /* u8  ep_bLength; */
-                    /* u8  ep_bDescriptorType; Endpoint */
-        USB_DT_ENDPOINT,
-                    /* u8  ep_bEndpointAddress; OUT Endpoint 3 */
-        CCID_BULK_OUT_EP,
-        0x02,       /* u8  ep_bmAttributes; Bulk */
-        0x40, 0x00, /* u16 ep_wMaxPacketSize; */
-        0x00,       /* u8  ep_bInterval; */
+enum {
+    STR_MANUFACTURER = 1,
+    STR_PRODUCT,
+    STR_SERIALNUMBER,
+    STR_INTERFACE,
+};
 
+static const USBDescStrings desc_strings = {
+    [STR_MANUFACTURER]  = "QEMU " QEMU_VERSION,
+    [STR_PRODUCT]       = "QEMU USB CCID",
+    [STR_SERIALNUMBER]  = "1",
+    [STR_INTERFACE]     = "CCID Interface",
+};
+
+static const USBDescIface desc_iface0 = {
+    .bInterfaceNumber              = 0,
+    .bNumEndpoints                 = 3,
+    .bInterfaceClass               = 0x0b,
+    .bInterfaceSubClass            = 0x00,
+    .bInterfaceProtocol            = 0x00,
+    .iInterface                    = STR_INTERFACE,
+    .ndesc                         = 1,
+    .descs = (USBDescOther[]) {
+        {
+            /* smartcard descriptor */
+            .data = qemu_ccid_descriptor,
+        },
+    },
+    .eps = (USBDescEndpoint[]) {
+        {
+            .bEndpointAddress      = USB_DIR_IN | CCID_INT_IN_EP,
+            .bmAttributes          = USB_ENDPOINT_XFER_INT,
+            .bInterval             = 255,
+            .wMaxPacketSize        = 64,
+        },{
+            .bEndpointAddress      = USB_DIR_IN | CCID_BULK_IN_EP,
+            .bmAttributes          = USB_ENDPOINT_XFER_BULK,
+            .wMaxPacketSize        = 64,
+        },{
+            .bEndpointAddress      = USB_DIR_OUT | CCID_BULK_OUT_EP,
+            .bmAttributes          = USB_ENDPOINT_XFER_BULK,
+            .wMaxPacketSize        = 64,
+        },
+    }
+};
+
+static const USBDescDevice desc_device = {
+    .bcdUSB                        = 0x0110,
+    .bMaxPacketSize0               = 64,
+    .bNumConfigurations            = 1,
+    .confs = (USBDescConfig[]) {
+        {
+            .bNumInterfaces        = 1,
+            .bConfigurationValue   = 1,
+            .bmAttributes          = 0xa0,
+            .bMaxPower             = 50,
+            .nif = 1,
+            .ifs = &desc_iface0,
+        },
+    },
+};
+
+static const USBDesc desc_ccid = {
+    .id = {
+        .idVendor          = CCID_VENDOR_ID,
+        .idProduct         = CCID_PRODUCT_ID,
+        .bcdDevice         = CCID_DEVICE_VERSION,
+        .iManufacturer     = STR_MANUFACTURER,
+        .iProduct          = STR_PRODUCT,
+        .iSerialNumber     = STR_SERIALNUMBER,
+    },
+    .full = &desc_device,
+    .str  = desc_strings,
 };
 
 static bool ccid_has_pending_answers(USBCCIDState *s)
@@ -610,87 +605,12 @@ static int ccid_handle_control(USBDevice *dev, USBPacket *p, int request,
     int ret = 0;
 
     DPRINTF(s, 1, "got control %x, value %x\n", request, value);
+    ret = usb_desc_handle_control(dev, p, request, value, index, length, data);
+    if (ret >= 0) {
+        return ret;
+    }
+
     switch (request) {
-    case DeviceRequest | USB_REQ_GET_STATUS:
-        data[0] = (1 << USB_DEVICE_SELF_POWERED) |
-            (dev->remote_wakeup << USB_DEVICE_REMOTE_WAKEUP);
-        data[1] = 0x00;
-        ret = 2;
-        break;
-    case DeviceOutRequest | USB_REQ_CLEAR_FEATURE:
-        if (value == USB_DEVICE_REMOTE_WAKEUP) {
-            dev->remote_wakeup = 0;
-        } else {
-            goto fail;
-        }
-        ret = 0;
-        break;
-    case DeviceOutRequest | USB_REQ_SET_FEATURE:
-        if (value == USB_DEVICE_REMOTE_WAKEUP) {
-            dev->remote_wakeup = 1;
-        } else {
-            goto fail;
-        }
-        ret = 0;
-        break;
-    case DeviceOutRequest | USB_REQ_SET_ADDRESS:
-        dev->addr = value;
-        ret = 0;
-        break;
-    case DeviceRequest | USB_REQ_GET_DESCRIPTOR:
-        switch (value >> 8) {
-        case USB_DT_DEVICE:
-            memcpy(data, qemu_ccid_dev_descriptor,
-                   sizeof(qemu_ccid_dev_descriptor));
-            ret = sizeof(qemu_ccid_dev_descriptor);
-            break;
-        case USB_DT_CONFIG:
-            memcpy(data, qemu_ccid_config_descriptor,
-                   sizeof(qemu_ccid_config_descriptor));
-            ret = sizeof(qemu_ccid_config_descriptor);
-            break;
-        case USB_DT_STRING:
-            switch (value & 0xff) {
-            case 0:
-                /* language ids */
-                data[0] = 4;
-                data[1] = 3;
-                data[2] = 0x09;
-                data[3] = 0x04;
-                ret = 4;
-                break;
-            case 1:
-                /* vendor description */
-                ret = set_usb_string(data, CCID_VENDOR_DESCRIPTION);
-                break;
-            case 2:
-                /* product description */
-                ret = set_usb_string(data, CCID_PRODUCT_DESCRIPTION);
-                break;
-            case 3:
-                /* serial number */
-                ret = set_usb_string(data, CCID_SERIAL_NUMBER_STRING);
-                break;
-            case 4:
-                /* interface name */
-                ret = set_usb_string(data, CCID_INTERFACE_NAME);
-                break;
-            default:
-                goto fail;
-            }
-            break;
-        default:
-            goto fail;
-        }
-        break;
-    case DeviceRequest | USB_REQ_GET_CONFIGURATION:
-        data[0] = 1;
-        ret = 1;
-        break;
-    case DeviceOutRequest | USB_REQ_SET_CONFIGURATION:
-        /* Only one configuration - we just ignore the request */
-        ret = 0;
-        break;
     case DeviceRequest | USB_REQ_GET_INTERFACE:
         data[0] = 0;
         ret = 1;
@@ -698,9 +618,6 @@ static int ccid_handle_control(USBDevice *dev, USBPacket *p, int request,
     case InterfaceOutRequest | USB_REQ_SET_INTERFACE:
         ret = 0;
         break;
-    case EndpointOutRequest | USB_REQ_CLEAR_FEATURE:
-        ret = 0;
-        break;
 
         /* Class specific requests.  */
     case InterfaceOutClass | CCID_CONTROL_ABORT:
@@ -716,7 +633,6 @@ static int ccid_handle_control(USBDevice *dev, USBPacket *p, int request,
         ret = USB_RET_STALL;
         break;
     default:
-fail:
         DPRINTF(s, 1, "got unsupported/bogus control %x, value %x\n",
                 request, value);
         ret = USB_RET_STALL;
@@ -895,6 +811,7 @@ static void ccid_on_slot_change(USBCCIDState *s, bool full)
         s->bmSlotICCState |= SLOT_0_CHANGED_MASK;
     }
     s->notify_slot_change = true;
+    usb_wakeup(&s->dev);
 }
 
 static void ccid_write_data_block_error(
@@ -1075,6 +992,7 @@ static int ccid_handle_data(USBDevice *dev, USBPacket *p)
             break;
         default:
             DPRINTF(s, 1, "Bad endpoint\n");
+            ret = USB_RET_STALL;
             break;
         }
         break;
@@ -1256,6 +1174,7 @@ static int ccid_initfn(USBDevice *dev)
 {
     USBCCIDState *s = DO_UPCAST(USBCCIDState, dev, dev);
 
+    usb_desc_init(dev);
     qbus_create_inplace(&s->bus.qbus, &ccid_bus_info, &dev->qdev, NULL);
     s->bus.qbus.allow_hotplug = 1;
     s->card = NULL;
@@ -1381,6 +1300,7 @@ static struct USBDeviceInfo ccid_info = {
     .qdev.desc      = "CCID Rev 1.1 smartcard reader",
     .qdev.size      = sizeof(USBCCIDState),
     .init           = ccid_initfn,
+    .usb_desc       = &desc_ccid,
     .handle_packet  = usb_generic_handle_packet,
     .handle_reset   = ccid_handle_reset,
     .handle_control = ccid_handle_control,
diff --git a/hw/usb-desc.h b/hw/usb-desc.h
index 9d7ed599ce..5c14e4abdc 100644
--- a/hw/usb-desc.h
+++ b/hw/usb-desc.h
@@ -75,7 +75,7 @@ struct USBDescEndpoint {
 
 struct USBDescOther {
     uint8_t                   length;
-    uint8_t                   *data;
+    const uint8_t             *data;
 };
 
 typedef const char *USBDescStrings[256];
diff --git a/hw/usb-ehci.c b/hw/usb-ehci.c
index 47a7fb9de4..e9e0789795 100644
--- a/hw/usb-ehci.c
+++ b/hw/usb-ehci.c
@@ -149,6 +149,7 @@ typedef enum {
     EST_FETCHENTRY,
     EST_FETCHQH,
     EST_FETCHITD,
+    EST_FETCHSITD,
     EST_ADVANCEQUEUE,
     EST_FETCHQTD,
     EST_EXECUTE,
@@ -646,6 +647,13 @@ static void ehci_trace_itd(EHCIState *s, target_phys_addr_t addr, EHCIitd *itd)
                        get_field(itd->bufptr[0], ITD_BUFPTR_DEVADDR));
 }
 
+static void ehci_trace_sitd(EHCIState *s, target_phys_addr_t addr,
+                            EHCIsitd *sitd)
+{
+    trace_usb_ehci_sitd(addr, sitd->next,
+                        (bool)(sitd->results & SITD_RESULTS_ACTIVE));
+}
+
 /* queue management */
 
 static EHCIQueue *ehci_alloc_queue(EHCIState *ehci, int async)
@@ -849,8 +857,8 @@ static void ehci_reset(void *opaque)
      */
     for(i = 0; i < NB_PORTS; i++) {
         devs[i] = s->ports[i].dev;
-        if (devs[i]) {
-            usb_attach(&s->ports[i], NULL);
+        if (devs[i] && devs[i]->attached) {
+            usb_detach(&s->ports[i]);
         }
     }
 
@@ -870,8 +878,8 @@ static void ehci_reset(void *opaque)
         } else {
             s->portsc[i] = PORTSC_PPOWER;
         }
-        if (devs[i]) {
-            usb_attach(&s->ports[i], devs[i]);
+        if (devs[i] && devs[i]->attached) {
+            usb_attach(&s->ports[i]);
         }
     }
     ehci_queues_rip_all(s);
@@ -937,15 +945,15 @@ static void handle_port_owner_write(EHCIState *s, int port, uint32_t owner)
         return;
     }
 
-    if (dev) {
-        usb_attach(&s->ports[port], NULL);
+    if (dev && dev->attached) {
+        usb_detach(&s->ports[port]);
     }
 
     *portsc &= ~PORTSC_POWNER;
     *portsc |= owner;
 
-    if (dev) {
-        usb_attach(&s->ports[port], dev);
+    if (dev && dev->attached) {
+        usb_attach(&s->ports[port]);
     }
 }
 
@@ -969,8 +977,8 @@ static void handle_port_status_write(EHCIState *s, int port, uint32_t val)
 
     if (!(val & PORTSC_PRESET) &&(*portsc & PORTSC_PRESET)) {
         trace_usb_ehci_port_reset(port, 0);
-        if (dev) {
-            usb_attach(&s->ports[port], dev);
+        if (dev && dev->attached) {
+            usb_attach(&s->ports[port]);
             usb_send_msg(dev, USB_MSG_RESET);
             *portsc &= ~PORTSC_CSC;
         }
@@ -979,7 +987,7 @@ static void handle_port_status_write(EHCIState *s, int port, uint32_t val)
          *  Table 2.16 Set the enable bit(and enable bit change) to indicate
          *  to SW that this port has a high speed device attached
          */
-        if (dev && (dev->speedmask & USB_SPEED_MASK_HIGH)) {
+        if (dev && dev->attached && (dev->speedmask & USB_SPEED_MASK_HIGH)) {
             val |= PORTSC_PED;
         }
     }
@@ -1584,8 +1592,13 @@ static int ehci_state_fetchentry(EHCIState *ehci, int async)
         again = 1;
         break;
 
+    case NLPTR_TYPE_STITD:
+        ehci_set_state(ehci, async, EST_FETCHSITD);
+        again = 1;
+        break;
+
     default:
-        // TODO: handle siTD and FSTN types
+        /* TODO: handle FSTN type */
         fprintf(stderr, "FETCHENTRY: entry at %X is of type %d "
                 "which is not supported yet\n", entry, NLPTR_TYPE_GET(entry));
         return -1;
@@ -1701,6 +1714,30 @@ static int ehci_state_fetchitd(EHCIState *ehci, int async)
     return 1;
 }
 
+static int ehci_state_fetchsitd(EHCIState *ehci, int async)
+{
+    uint32_t entry;
+    EHCIsitd sitd;
+
+    assert(!async);
+    entry = ehci_get_fetch_addr(ehci, async);
+
+    get_dwords(NLPTR_GET(entry), (uint32_t *)&sitd,
+               sizeof(EHCIsitd) >> 2);
+    ehci_trace_sitd(ehci, entry, &sitd);
+
+    if (!(sitd.results & SITD_RESULTS_ACTIVE)) {
+        /* siTD is not active, nothing to do */;
+    } else {
+        /* TODO: split transfers are not implemented */
+        fprintf(stderr, "WARNING: Skipping active siTD\n");
+    }
+
+    ehci_set_fetch_addr(ehci, async, sitd.next);
+    ehci_set_state(ehci, async, EST_FETCHENTRY);
+    return 1;
+}
+
 /* Section 4.10.2 - paragraph 3 */
 static int ehci_state_advqueue(EHCIQueue *q, int async)
 {
@@ -1976,6 +2013,10 @@ static void ehci_advance_state(EHCIState *ehci,
             again = ehci_state_fetchitd(ehci, async);
             break;
 
+        case EST_FETCHSITD:
+            again = ehci_state_fetchsitd(ehci, async);
+            break;
+
         case EST_ADVANCEQUEUE:
             again = ehci_state_advqueue(q, async);
             break;
diff --git a/hw/usb-hub.c b/hw/usb-hub.c
index c49c547d0c..286e3ad85d 100644
--- a/hw/usb-hub.c
+++ b/hw/usb-hub.c
@@ -213,16 +213,6 @@ static void usb_hub_complete(USBPort *port, USBPacket *packet)
     usb_packet_complete(&s->dev, packet);
 }
 
-static void usb_hub_handle_attach(USBDevice *dev)
-{
-    USBHubState *s = DO_UPCAST(USBHubState, dev, dev);
-    int i;
-
-    for (i = 0; i < NUM_PORTS; i++) {
-        usb_port_location(&s->ports[i].port, dev->port, i+1);
-    }
-}
-
 static void usb_hub_handle_reset(USBDevice *dev)
 {
     /* XXX: do it */
@@ -499,6 +489,7 @@ static int usb_hub_initfn(USBDevice *dev)
         usb_register_port(usb_bus_from_device(dev),
                           &port->port, s, i, &usb_hub_port_ops,
                           USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL);
+        usb_port_location(&port->port, dev->port, i+1);
         port->wPortStatus = PORT_STAT_POWER;
         port->wPortChange = 0;
     }
@@ -537,7 +528,6 @@ static struct USBDeviceInfo hub_info = {
     .usb_desc       = &desc_hub,
     .init           = usb_hub_initfn,
     .handle_packet  = usb_hub_handle_packet,
-    .handle_attach  = usb_hub_handle_attach,
     .handle_reset   = usb_hub_handle_reset,
     .handle_control = usb_hub_handle_control,
     .handle_data    = usb_hub_handle_data,
diff --git a/hw/usb-msd.c b/hw/usb-msd.c
index 4072efd4b7..e92434cc94 100644
--- a/hw/usb-msd.c
+++ b/hw/usb-msd.c
@@ -518,7 +518,7 @@ static int usb_msd_initfn(USBDevice *dev)
      *
      * The hack is probably a bad idea.
      */
-    bdrv_detach(bs, &s->dev.qdev);
+    bdrv_detach_dev(bs, &s->dev.qdev);
     s->conf.bs = NULL;
 
     if (!s->serial) {
diff --git a/hw/usb-musb.c b/hw/usb-musb.c
index 799fa6e187..01e2e7c389 100644
--- a/hw/usb-musb.c
+++ b/hw/usb-musb.c
@@ -314,7 +314,7 @@ struct MUSBEndPoint {
 };
 
 struct MUSBState {
-    qemu_irq *irqs;
+    qemu_irq irqs[musb_irq_max];
     USBBus bus;
     USBPort port;
 
@@ -340,14 +340,12 @@ struct MUSBState {
     MUSBEndPoint ep[16];
 };
 
-struct MUSBState *musb_init(qemu_irq *irqs)
+void musb_reset(MUSBState *s)
 {
-    MUSBState *s = g_malloc0(sizeof(*s));
     int i;
 
-    s->irqs = irqs;
-
     s->faddr = 0x00;
+    s->devctl = 0;
     s->power = MGC_M_POWER_HSENAB;
     s->tx_intr = 0x0000;
     s->rx_intr = 0x0000;
@@ -357,6 +355,10 @@ struct MUSBState *musb_init(qemu_irq *irqs)
     s->mask = 0x06;
     s->idx = 0;
 
+    s->setup_len = 0;
+    s->session = 0;
+    memset(s->buf, 0, sizeof(s->buf));
+
     /* TODO: _DW */
     s->ep[0].config = MGC_M_CONFIGDATA_SOFTCONE | MGC_M_CONFIGDATA_DYNFIFO;
     for (i = 0; i < 16; i ++) {
@@ -368,8 +370,20 @@ struct MUSBState *musb_init(qemu_irq *irqs)
         usb_packet_init(&s->ep[i].packey[0].p);
         usb_packet_init(&s->ep[i].packey[1].p);
     }
+}
+
+struct MUSBState *musb_init(DeviceState *parent_device, int gpio_base)
+{
+    MUSBState *s = g_malloc0(sizeof(*s));
+    int i;
+
+    for (i = 0; i < musb_irq_max; i++) {
+        s->irqs[i] = qdev_get_gpio_in(parent_device, gpio_base + i);
+    }
+
+    musb_reset(s);
 
-    usb_bus_new(&s->bus, &musb_bus_ops, NULL /* FIXME */);
+    usb_bus_new(&s->bus, &musb_bus_ops, parent_device);
     usb_register_port(&s->bus, &s->port, s, 0, &musb_port_ops,
                       USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL);
 
diff --git a/hw/usb-ohci.c b/hw/usb-ohci.c
index d30db3f92f..503ca2d31f 100644
--- a/hw/usb-ohci.c
+++ b/hw/usb-ohci.c
@@ -448,8 +448,8 @@ static void ohci_reset(void *opaque)
       {
         port = &ohci->rhport[i];
         port->ctrl = 0;
-        if (port->port.dev) {
-            usb_attach(&port->port, port->port.dev);
+        if (port->port.dev && port->port.dev->attached) {
+            usb_attach(&port->port);
         }
       }
     if (ohci->async_td) {
diff --git a/hw/usb-uhci.c b/hw/usb-uhci.c
index 6ca7ca81eb..64f7b36c00 100644
--- a/hw/usb-uhci.c
+++ b/hw/usb-uhci.c
@@ -340,8 +340,8 @@ static void uhci_reset(void *opaque)
     for(i = 0; i < NB_PORTS; i++) {
         port = &s->ports[i];
         port->ctrl = 0x0080;
-        if (port->port.dev) {
-            usb_attach(&port->port, port->port.dev);
+        if (port->port.dev && port->port.dev->attached) {
+            usb_attach(&port->port);
         }
     }
 
@@ -446,7 +446,7 @@ static void uhci_ioport_writew(void *opaque, uint32_t addr, uint32_t val)
             for(i = 0; i < NB_PORTS; i++) {
                 port = &s->ports[i];
                 dev = port->port.dev;
-                if (dev) {
+                if (dev && dev->attached) {
                     usb_send_msg(dev, USB_MSG_RESET);
                 }
             }
@@ -486,7 +486,7 @@ static void uhci_ioport_writew(void *opaque, uint32_t addr, uint32_t val)
                 return;
             port = &s->ports[n];
             dev = port->port.dev;
-            if (dev) {
+            if (dev && dev->attached) {
                 /* port reset */
                 if ( (val & UHCI_PORT_RESET) &&
                      !(port->ctrl & UHCI_PORT_RESET) ) {
@@ -660,8 +660,9 @@ static int uhci_broadcast_packet(UHCIState *s, USBPacket *p)
         UHCIPort *port = &s->ports[i];
         USBDevice *dev = port->port.dev;
 
-        if (dev && (port->ctrl & UHCI_PORT_EN))
+        if (dev && dev->attached && (port->ctrl & UHCI_PORT_EN)) {
             ret = usb_handle_packet(dev, p);
+        }
     }
 
     DPRINTF("uhci: packet exit. ret %d len %zd\n", ret, p->iov.size);
diff --git a/hw/usb.c b/hw/usb.c
index 685e775a00..fa90204c5e 100644
--- a/hw/usb.c
+++ b/hw/usb.c
@@ -27,26 +27,23 @@
 #include "usb.h"
 #include "iov.h"
 
-void usb_attach(USBPort *port, USBDevice *dev)
+void usb_attach(USBPort *port)
 {
-    if (dev != NULL) {
-        /* attach */
-        if (port->dev) {
-            usb_attach(port, NULL);
-        }
-        dev->port = port;
-        port->dev = dev;
-        port->ops->attach(port);
-        usb_send_msg(dev, USB_MSG_ATTACH);
-    } else {
-        /* detach */
-        dev = port->dev;
-        assert(dev);
-        port->ops->detach(port);
-        usb_send_msg(dev, USB_MSG_DETACH);
-        dev->port = NULL;
-        port->dev = NULL;
-    }
+    USBDevice *dev = port->dev;
+
+    assert(dev != NULL);
+    assert(dev->attached);
+    port->ops->attach(port);
+    usb_send_msg(dev, USB_MSG_ATTACH);
+}
+
+void usb_detach(USBPort *port)
+{
+    USBDevice *dev = port->dev;
+
+    assert(dev != NULL);
+    port->ops->detach(port);
+    usb_send_msg(dev, USB_MSG_DETACH);
 }
 
 void usb_wakeup(USBDevice *dev)
@@ -338,8 +335,8 @@ void usb_packet_complete(USBDevice *dev, USBPacket *p)
 {
     /* Note: p->owner != dev is possible in case dev is a hub */
     assert(p->owner != NULL);
-    dev->port->ops->complete(dev->port, p);
     p->owner = NULL;
+    dev->port->ops->complete(dev->port, p);
 }
 
 /* Cancel an active packet.  The packed must have been deferred by
diff --git a/hw/usb.h b/hw/usb.h
index d784448290..c08d469496 100644
--- a/hw/usb.h
+++ b/hw/usb.h
@@ -304,7 +304,8 @@ int usb_handle_packet(USBDevice *dev, USBPacket *p);
 void usb_packet_complete(USBDevice *dev, USBPacket *p);
 void usb_cancel_packet(USBPacket * p);
 
-void usb_attach(USBPort *port, USBDevice *dev);
+void usb_attach(USBPort *port);
+void usb_detach(USBPort *port);
 void usb_wakeup(USBDevice *dev);
 int usb_generic_handle_packet(USBDevice *s, USBPacket *p);
 void usb_generic_async_ctrl_complete(USBDevice *s, USBPacket *p);
@@ -337,11 +338,13 @@ enum musb_irq_source_e {
     musb_irq_tx,
     musb_set_vbus,
     musb_set_session,
-    __musb_irq_max,
+    /* Add new interrupts here */
+    musb_irq_max, /* total number of interrupts defined */
 };
 
 typedef struct MUSBState MUSBState;
-MUSBState *musb_init(qemu_irq *irqs);
+MUSBState *musb_init(DeviceState *parent_device, int gpio_base);
+void musb_reset(MUSBState *s);
 uint32_t musb_core_intr_get(MUSBState *s);
 void musb_core_intr_clear(MUSBState *s, uint32_t mask);
 void musb_set_size(MUSBState *s, int epnum, int size, int is_tx);
@@ -378,6 +381,8 @@ int usb_register_companion(const char *masterbus, USBPort *ports[],
                            void *opaque, USBPortOps *ops, int speedmask);
 void usb_port_location(USBPort *downstream, USBPort *upstream, int portnr);
 void usb_unregister_port(USBBus *bus, USBPort *port);
+int usb_claim_port(USBDevice *dev);
+void usb_release_port(USBDevice *dev);
 int usb_device_attach(USBDevice *dev);
 int usb_device_detach(USBDevice *dev);
 int usb_device_delete_addr(int busnr, int addr);
diff --git a/hw/virtex_ml507.c b/hw/virtex_ml507.c
index 333050cdac..7459b0bbe9 100644
--- a/hw/virtex_ml507.c
+++ b/hw/virtex_ml507.c
@@ -196,7 +196,6 @@ static void virtex_init(ram_addr_t ram_size,
     target_phys_addr_t ram_base = 0;
     DriveInfo *dinfo;
     ram_addr_t phys_ram;
-    ram_addr_t phys_flash;
     qemu_irq irq[32], *cpu_irq;
     clk_setup_t clk_setup[7];
     int kernel_size;
@@ -215,9 +214,8 @@ static void virtex_init(ram_addr_t ram_size,
     phys_ram = qemu_ram_alloc(NULL, "ram", ram_size);
     cpu_register_physical_memory(ram_base, ram_size, phys_ram | IO_MEM_RAM);
 
-    phys_flash = qemu_ram_alloc(NULL, "virtex.flash", FLASH_SIZE);
     dinfo = drive_get(IF_PFLASH, 0, 0);
-    pflash_cfi01_register(0xfc000000, phys_flash,
+    pflash_cfi01_register(0xfc000000, NULL, "virtex.flash", FLASH_SIZE,
                           dinfo ? dinfo->bdrv : NULL, (64 * 1024),
                           FLASH_SIZE >> 16,
                           1, 0x89, 0x18, 0x0000, 0x0, 1);
diff --git a/hw/virtio-blk.c b/hw/virtio-blk.c
index 2a8ccd0aa9..4df23f4228 100644
--- a/hw/virtio-blk.c
+++ b/hw/virtio-blk.c
@@ -543,15 +543,17 @@ static int virtio_blk_load(QEMUFile *f, void *opaque, int version_id)
     return 0;
 }
 
-static void virtio_blk_change_cb(void *opaque, int reason)
+static void virtio_blk_resize(void *opaque)
 {
     VirtIOBlock *s = opaque;
 
-    if (reason & CHANGE_SIZE) {
-        virtio_notify_config(&s->vdev);
-    }
+    virtio_notify_config(&s->vdev);
 }
 
+static const BlockDevOps virtio_block_ops = {
+    .resize_cb = virtio_blk_resize,
+};
+
 VirtIODevice *virtio_blk_init(DeviceState *dev, BlockConf *conf,
                               char **serial)
 {
@@ -598,7 +600,7 @@ VirtIODevice *virtio_blk_init(DeviceState *dev, BlockConf *conf,
     register_savevm(dev, "virtio-blk", virtio_blk_id++, 2,
                     virtio_blk_save, virtio_blk_load, s);
     bdrv_set_removable(s->bs, 0);
-    bdrv_set_change_cb(s->bs, virtio_blk_change_cb, s);
+    bdrv_set_dev_ops(s->bs, &virtio_block_ops, s);
     s->bs->buffer_alignment = conf->logical_block_size;
 
     add_boot_device_path(conf->bootindex, dev, "/disk@0,0");
diff --git a/hw/xen_disk.c b/hw/xen_disk.c
index bd5c66916b..da531a67dd 100644
--- a/hw/xen_disk.c
+++ b/hw/xen_disk.c
@@ -697,6 +697,7 @@ static int blk_init(struct XenDevice *xendev)
         xen_be_printf(&blkdev->xendev, 2, "get configured bdrv (cmdline setup)\n");
         blkdev->bs = blkdev->dinfo->bdrv;
     }
+    bdrv_attach_dev_nofail(blkdev->bs, blkdev);
     blkdev->file_blk  = BLOCK_SIZE;
     blkdev->file_size = bdrv_getlength(blkdev->bs);
     if (blkdev->file_size < 0) {
diff --git a/hw/z2.c b/hw/z2.c
index f93a1bf0fe..b6ae608657 100644
--- a/hw/z2.c
+++ b/hw/z2.c
@@ -305,7 +305,7 @@ static void z2_init(ram_addr_t ram_size,
     }
 
     if (!pflash_cfi01_register(Z2_FLASH_BASE,
-                               qemu_ram_alloc(NULL, "z2.flash0", Z2_FLASH_SIZE),
+                               NULL, "z2.flash0", Z2_FLASH_SIZE,
                                dinfo->bdrv, sector_len,
                                Z2_FLASH_SIZE / sector_len, 4, 0, 0, 0, 0,
                                be)) {