Merge remote-tracking branch 'stefanha/trivial-patches' into staging
diff --git a/Makefile.hw b/Makefile.hw
index 659e441..63eb7e4 100644
--- a/Makefile.hw
+++ b/Makefile.hw
@@ -10,6 +10,7 @@
 $(call set-vpath, $(SRC_PATH):$(SRC_PATH)/hw)
 
 QEMU_CFLAGS+=-I..
+QEMU_CFLAGS += $(GLIB_CFLAGS)
 
 include $(SRC_PATH)/Makefile.objs
 
diff --git a/Makefile.target b/Makefile.target
index e280bf6..c9957ae 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -195,7 +195,6 @@
 obj-y += vhost_net.o
 obj-$(CONFIG_VHOST_NET) += vhost.o
 obj-$(CONFIG_REALLY_VIRTFS) += 9pfs/virtio-9p-device.o
-obj-y += rwhandler.o
 obj-$(CONFIG_KVM) += kvm.o kvm-all.o
 obj-$(CONFIG_NO_KVM) += kvm-stub.o
 obj-y += memory.o
diff --git a/fsdev/file-op-9p.h b/fsdev/file-op-9p.h
index af9daf7..1eda342 100644
--- a/fsdev/file-op-9p.h
+++ b/fsdev/file-op-9p.h
@@ -78,7 +78,7 @@
     int (*open2)(FsContext *, const char *, int, FsCred *);
     void (*rewinddir)(FsContext *, DIR *);
     off_t (*telldir)(FsContext *, DIR *);
-    struct dirent *(*readdir)(FsContext *, DIR *);
+    int (*readdir_r)(FsContext *, DIR *, struct dirent *, struct dirent **);
     void (*seekdir)(FsContext *, DIR *, off_t);
     ssize_t (*preadv)(FsContext *, int, const struct iovec *, int, off_t);
     ssize_t (*pwritev)(FsContext *, int, const struct iovec *, int, off_t);
diff --git a/hw/9pfs/codir.c b/hw/9pfs/codir.c
index 28f2ad7..3a257b9 100644
--- a/hw/9pfs/codir.c
+++ b/hw/9pfs/codir.c
@@ -17,16 +17,16 @@
 #include "qemu-coroutine.h"
 #include "virtio-9p-coth.h"
 
-int v9fs_co_readdir(V9fsState *s, V9fsFidState *fidp, struct dirent **dent)
+int v9fs_co_readdir_r(V9fsState *s, V9fsFidState *fidp, struct dirent *dent,
+                      struct dirent **result)
 {
     int err;
 
     v9fs_co_run_in_worker(
         {
             errno = 0;
-            /*FIXME!! need to switch to readdir_r */
-            *dent = s->ops->readdir(&s->ctx, fidp->fs.dir);
-            if (!*dent && errno) {
+            err = s->ops->readdir_r(&s->ctx, fidp->fs.dir, dent, result);
+            if (!*result && errno) {
                 err = -errno;
             } else {
                 err = 0;
@@ -83,3 +83,35 @@
         });
     return err;
 }
+
+int v9fs_co_opendir(V9fsState *s, V9fsFidState *fidp)
+{
+    int err;
+
+    v9fs_co_run_in_worker(
+        {
+            fidp->fs.dir = s->ops->opendir(&s->ctx, fidp->path.data);
+            if (!fidp->fs.dir) {
+                err = -errno;
+            } else {
+                err = 0;
+            }
+        });
+    return err;
+}
+
+int v9fs_co_closedir(V9fsState *s, V9fsFidState *fidp)
+{
+    int err;
+    DIR *dir;
+
+    dir = fidp->fs.dir;
+    v9fs_co_run_in_worker(
+        {
+            err = s->ops->closedir(&s->ctx, dir);
+            if (err < 0) {
+                err = -errno;
+            }
+        });
+    return err;
+}
diff --git a/hw/9pfs/cofile.c b/hw/9pfs/cofile.c
index a4c0ae7..e388146 100644
--- a/hw/9pfs/cofile.c
+++ b/hw/9pfs/cofile.c
@@ -30,3 +30,134 @@
         });
     return err;
 }
+
+int v9fs_co_fstat(V9fsState *s, int fd, struct stat *stbuf)
+{
+    int err;
+
+    v9fs_co_run_in_worker(
+        {
+            err = s->ops->fstat(&s->ctx, fd, stbuf);
+            if (err < 0) {
+                err = -errno;
+            }
+        });
+    return err;
+}
+
+int v9fs_co_open(V9fsState *s, V9fsFidState *fidp, int flags)
+{
+    int err;
+
+    v9fs_co_run_in_worker(
+        {
+            fidp->fs.fd = s->ops->open(&s->ctx, fidp->path.data, flags);
+            if (fidp->fs.fd == -1) {
+                err = -errno;
+            } else {
+                err = 0;
+            }
+        });
+    return err;
+}
+
+int v9fs_co_open2(V9fsState *s, V9fsFidState *fidp, char *fullname, gid_t gid,
+                  int flags, int mode)
+{
+    int err;
+    FsCred cred;
+
+    cred_init(&cred);
+    cred.fc_mode = mode & 07777;
+    cred.fc_uid = fidp->uid;
+    cred.fc_gid = gid;
+    v9fs_co_run_in_worker(
+        {
+            fidp->fs.fd = s->ops->open2(&s->ctx, fullname, flags, &cred);
+            err = 0;
+            if (fidp->fs.fd == -1) {
+                err = -errno;
+            }
+        });
+    return err;
+}
+
+int v9fs_co_close(V9fsState *s, V9fsFidState *fidp)
+{
+    int fd;
+    int err;
+
+    fd = fidp->fs.fd;
+    v9fs_co_run_in_worker(
+        {
+            err = s->ops->close(&s->ctx, fd);
+            if (err < 0) {
+                err = -errno;
+            }
+        });
+    return err;
+}
+
+int v9fs_co_fsync(V9fsState *s, V9fsFidState *fidp, int datasync)
+{
+    int fd;
+    int err;
+
+    fd = fidp->fs.fd;
+    v9fs_co_run_in_worker(
+        {
+            err = s->ops->fsync(&s->ctx, fd, datasync);
+            if (err < 0) {
+                err = -errno;
+            }
+        });
+    return err;
+}
+
+int v9fs_co_link(V9fsState *s, V9fsString *oldpath, V9fsString *newpath)
+{
+    int err;
+
+    v9fs_co_run_in_worker(
+        {
+            err = s->ops->link(&s->ctx, oldpath->data, newpath->data);
+            if (err < 0) {
+                err = -errno;
+            }
+        });
+    return err;
+}
+
+int v9fs_co_pwritev(V9fsState *s, V9fsFidState *fidp,
+                    struct iovec *iov, int iovcnt, int64_t offset)
+{
+    int fd;
+    int err;
+
+    fd = fidp->fs.fd;
+    v9fs_co_run_in_worker(
+        {
+            err = s->ops->pwritev(&s->ctx, fd, iov, iovcnt, offset);
+            if (err < 0) {
+                err = -errno;
+            }
+        });
+    return err;
+}
+
+int v9fs_co_preadv(V9fsState *s, V9fsFidState *fidp,
+                   struct iovec *iov, int iovcnt, int64_t offset)
+{
+    int fd;
+    int err;
+
+    fd = fidp->fs.fd;
+    v9fs_co_run_in_worker(
+        {
+            err = s->ops->preadv(&s->ctx, fd, iov, iovcnt, offset);
+            if (err < 0) {
+                err = -errno;
+            }
+        });
+    return err;
+}
diff --git a/hw/9pfs/cofs.c b/hw/9pfs/cofs.c
index 1f10632..a78fccb 100644
--- a/hw/9pfs/cofs.c
+++ b/hw/9pfs/cofs.c
@@ -169,3 +169,23 @@
         });
     return err;
 }
+
+int v9fs_co_symlink(V9fsState *s, V9fsFidState *fidp,
+                    const char *oldpath, const char *newpath, gid_t gid)
+{
+    int err;
+    FsCred cred;
+
+    cred_init(&cred);
+    cred.fc_uid = fidp->uid;
+    cred.fc_gid = gid;
+    cred.fc_mode = 0777;
+    v9fs_co_run_in_worker(
+        {
+            err = s->ops->symlink(&s->ctx, oldpath, newpath, &cred);
+            if (err < 0) {
+                err = -errno;
+            }
+        });
+    return err;
+}
diff --git a/hw/9pfs/coxattr.c b/hw/9pfs/coxattr.c
index 2fba2c9..a289389 100644
--- a/hw/9pfs/coxattr.c
+++ b/hw/9pfs/coxattr.c
@@ -48,3 +48,37 @@
         });
     return err;
 }
+
+int v9fs_co_lsetxattr(V9fsState *s, V9fsString *path,
+                      V9fsString *xattr_name, void *value,
+                      size_t size, int flags)
+{
+    int err;
+
+    v9fs_co_run_in_worker(
+        {
+            err = s->ops->lsetxattr(&s->ctx, path->data,
+                                    xattr_name->data, value,
+                                    size, flags);
+            if (err < 0) {
+                err = -errno;
+            }
+        });
+    return err;
+}
+
+int v9fs_co_lremovexattr(V9fsState *s, V9fsString *path,
+                         V9fsString *xattr_name)
+{
+    int err;
+
+    v9fs_co_run_in_worker(
+        {
+            err = s->ops->lremovexattr(&s->ctx, path->data,
+                                       xattr_name->data);
+            if (err < 0) {
+                err = -errno;
+            }
+        });
+    return err;
+}
diff --git a/hw/9pfs/virtio-9p-coth.h b/hw/9pfs/virtio-9p-coth.h
index 11272d3..48defb7 100644
--- a/hw/9pfs/virtio-9p-coth.h
+++ b/hw/9pfs/virtio-9p-coth.h
@@ -57,8 +57,8 @@
 extern void co_run_in_worker_bh(void *);
 extern int v9fs_init_worker_threads(void);
 extern int v9fs_co_readlink(V9fsState *, V9fsString *, V9fsString *);
-extern int v9fs_co_readdir(V9fsState *, V9fsFidState *,
-                           struct dirent **);
+extern int v9fs_co_readdir_r(V9fsState *, V9fsFidState *,
+                           struct dirent *, struct dirent **result);
 extern off_t v9fs_co_telldir(V9fsState *, V9fsFidState *);
 extern void v9fs_co_seekdir(V9fsState *, V9fsFidState *, off_t);
 extern void v9fs_co_rewinddir(V9fsState *, V9fsFidState *);
@@ -76,4 +76,21 @@
 extern int v9fs_co_mkdir(V9fsState *, char *, mode_t, uid_t, gid_t);
 extern int v9fs_co_remove(V9fsState *, V9fsString *);
 extern int v9fs_co_rename(V9fsState *, V9fsString *, V9fsString *);
+extern int v9fs_co_fstat(V9fsState *, int, struct stat *);
+extern int v9fs_co_opendir(V9fsState *, V9fsFidState *);
+extern int v9fs_co_open(V9fsState *, V9fsFidState *, int);
+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_fsync(V9fsState *, V9fsFidState *, int);
+extern int v9fs_co_symlink(V9fsState *, V9fsFidState *, const char *,
+                           const char *, gid_t);
+extern int v9fs_co_link(V9fsState *, V9fsString *, V9fsString *);
+extern int v9fs_co_pwritev(V9fsState *, V9fsFidState *,
+                           struct iovec *, int, int64_t);
+extern int v9fs_co_preadv(V9fsState *, V9fsFidState *,
+                          struct iovec *, int, int64_t);
 #endif
diff --git a/hw/9pfs/virtio-9p-local.c b/hw/9pfs/virtio-9p-local.c
index 77904c3..61cbf8d 100644
--- a/hw/9pfs/virtio-9p-local.c
+++ b/hw/9pfs/virtio-9p-local.c
@@ -165,9 +165,10 @@
     return telldir(dir);
 }
 
-static struct dirent *local_readdir(FsContext *ctx, DIR *dir)
+static int local_readdir_r(FsContext *ctx, DIR *dir, struct dirent *entry,
+                         struct dirent **result)
 {
-    return readdir(dir);
+    return readdir_r(dir, entry, result);
 }
 
 static void local_seekdir(FsContext *ctx, DIR *dir, off_t off)
@@ -532,7 +533,7 @@
     .opendir = local_opendir,
     .rewinddir = local_rewinddir,
     .telldir = local_telldir,
-    .readdir = local_readdir,
+    .readdir_r = local_readdir_r,
     .seekdir = local_seekdir,
     .preadv = local_preadv,
     .pwritev = local_pwritev,
diff --git a/hw/9pfs/virtio-9p.c b/hw/9pfs/virtio-9p.c
index eb33636..ad70768 100644
--- a/hw/9pfs/virtio-9p.c
+++ b/hw/9pfs/virtio-9p.c
@@ -77,160 +77,6 @@
     credp->fc_rdev = -1;
 }
 
-static int v9fs_do_lstat(V9fsState *s, V9fsString *path, struct stat *stbuf)
-{
-    return s->ops->lstat(&s->ctx, path->data, stbuf);
-}
-
-static int v9fs_do_close(V9fsState *s, int fd)
-{
-    return s->ops->close(&s->ctx, fd);
-}
-
-static int v9fs_do_closedir(V9fsState *s, DIR *dir)
-{
-    return s->ops->closedir(&s->ctx, dir);
-}
-
-static int v9fs_do_open(V9fsState *s, V9fsString *path, int flags)
-{
-    return s->ops->open(&s->ctx, path->data, flags);
-}
-
-static DIR *v9fs_do_opendir(V9fsState *s, V9fsString *path)
-{
-    return s->ops->opendir(&s->ctx, path->data);
-}
-
-static void v9fs_do_rewinddir(V9fsState *s, DIR *dir)
-{
-    return s->ops->rewinddir(&s->ctx, dir);
-}
-
-static off_t v9fs_do_telldir(V9fsState *s, DIR *dir)
-{
-    return s->ops->telldir(&s->ctx, dir);
-}
-
-static void v9fs_do_seekdir(V9fsState *s, DIR *dir, off_t off)
-{
-    return s->ops->seekdir(&s->ctx, dir, off);
-}
-
-static int v9fs_do_preadv(V9fsState *s, int fd, const struct iovec *iov,
-                            int iovcnt, int64_t offset)
-{
-    return s->ops->preadv(&s->ctx, fd, iov, iovcnt, offset);
-}
-
-static int v9fs_do_pwritev(V9fsState *s, int fd, const struct iovec *iov,
-                       int iovcnt, int64_t offset)
-{
-    return s->ops->pwritev(&s->ctx, fd, iov, iovcnt, offset);
-}
-
-static int v9fs_do_chmod(V9fsState *s, V9fsString *path, mode_t mode)
-{
-    FsCred cred;
-    cred_init(&cred);
-    cred.fc_mode = mode;
-    return s->ops->chmod(&s->ctx, path->data, &cred);
-}
-
-static int v9fs_do_mknod(V9fsState *s, char *name,
-        mode_t mode, dev_t dev, uid_t uid, gid_t gid)
-{
-    FsCred cred;
-    cred_init(&cred);
-    cred.fc_uid = uid;
-    cred.fc_gid = gid;
-    cred.fc_mode = mode;
-    cred.fc_rdev = dev;
-    return s->ops->mknod(&s->ctx, name, &cred);
-}
-
-static int v9fs_do_fstat(V9fsState *s, int fd, struct stat *stbuf)
-{
-    return s->ops->fstat(&s->ctx, fd, stbuf);
-}
-
-static int v9fs_do_open2(V9fsState *s, char *fullname, uid_t uid, gid_t gid,
-        int flags, int mode)
-{
-    FsCred cred;
-
-    cred_init(&cred);
-    cred.fc_uid = uid;
-    cred.fc_gid = gid;
-    cred.fc_mode = mode & 07777;
-
-    return s->ops->open2(&s->ctx, fullname, flags, &cred);
-}
-
-static int v9fs_do_symlink(V9fsState *s, V9fsFidState *fidp,
-        const char *oldpath, const char *newpath, gid_t gid)
-{
-    FsCred cred;
-    cred_init(&cred);
-    cred.fc_uid = fidp->uid;
-    cred.fc_gid = gid;
-    cred.fc_mode = 0777;
-
-    return s->ops->symlink(&s->ctx, oldpath, newpath, &cred);
-}
-
-static int v9fs_do_link(V9fsState *s, V9fsString *oldpath, V9fsString *newpath)
-{
-    return s->ops->link(&s->ctx, oldpath->data, newpath->data);
-}
-
-static int v9fs_do_truncate(V9fsState *s, V9fsString *path, off_t size)
-{
-    return s->ops->truncate(&s->ctx, path->data, size);
-}
-
-static int v9fs_do_chown(V9fsState *s, V9fsString *path, uid_t uid, gid_t gid)
-{
-    FsCred cred;
-    cred_init(&cred);
-    cred.fc_uid = uid;
-    cred.fc_gid = gid;
-
-    return s->ops->chown(&s->ctx, path->data, &cred);
-}
-
-static int v9fs_do_utimensat(V9fsState *s, V9fsString *path,
-                                           const struct timespec times[2])
-{
-    return s->ops->utimensat(&s->ctx, path->data, times);
-}
-
-static int v9fs_do_fsync(V9fsState *s, int fd, int datasync)
-{
-    return s->ops->fsync(&s->ctx, fd, datasync);
-}
-
-static int v9fs_do_statfs(V9fsState *s, V9fsString *path, struct statfs *stbuf)
-{
-    return s->ops->statfs(&s->ctx, path->data, stbuf);
-}
-
-static int v9fs_do_lsetxattr(V9fsState *s, V9fsString *path,
-                             V9fsString *xattr_name,
-                             void *value, size_t size, int flags)
-{
-    return s->ops->lsetxattr(&s->ctx, path->data,
-                             xattr_name->data, value, size, flags);
-}
-
-static int v9fs_do_lremovexattr(V9fsState *s, V9fsString *path,
-                                V9fsString *xattr_name)
-{
-    return s->ops->lremovexattr(&s->ctx, path->data,
-                                xattr_name->data);
-}
-
-
 static void v9fs_string_init(V9fsString *str)
 {
     str->data = NULL;
@@ -437,12 +283,12 @@
         goto free_out;
     }
     if (fidp->fs.xattr.len) {
-        retval = v9fs_do_lsetxattr(s, &fidp->path, &fidp->fs.xattr.name,
+        retval = v9fs_co_lsetxattr(s, &fidp->path, &fidp->fs.xattr.name,
                                    fidp->fs.xattr.value,
                                    fidp->fs.xattr.len,
                                    fidp->fs.xattr.flags);
     } else {
-        retval = v9fs_do_lremovexattr(s, &fidp->path, &fidp->fs.xattr.name);
+        retval = v9fs_co_lremovexattr(s, &fidp->path, &fidp->fs.xattr.name);
     }
 free_out:
     v9fs_string_free(&fidp->fs.xattr.name);
@@ -472,15 +318,14 @@
     *fidpp = fidp->next;
 
     if (fidp->fid_type == P9_FID_FILE) {
-        v9fs_do_close(s, fidp->fs.fd);
+        retval = v9fs_co_close(s, fidp);
     } else if (fidp->fid_type == P9_FID_DIR) {
-        v9fs_do_closedir(s, fidp->fs.dir);
+        retval = v9fs_co_closedir(s, fidp);
     } 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;
 }
 
@@ -531,11 +376,10 @@
     struct stat stbuf;
     int err;
 
-    err = v9fs_do_lstat(s, &fidp->path, &stbuf);
-    if (err) {
+    err = v9fs_co_lstat(s, &fidp->path, &stbuf);
+    if (err < 0) {
         return err;
     }
-
     stat_to_qid(&stbuf, qidp);
     return 0;
 }
@@ -1161,8 +1005,8 @@
     int32_t fid, afid, n_uname;
     V9fsString uname, aname;
     V9fsFidState *fidp;
-    V9fsQID qid;
     size_t offset = 7;
+    V9fsQID qid;
     ssize_t err;
 
     pdu_unmarshal(pdu, offset, "ddssd", &fid, &afid, &uname, &aname, &n_uname);
@@ -1172,19 +1016,15 @@
         err = -EINVAL;
         goto out;
     }
-
     fidp->uid = n_uname;
-
     v9fs_string_sprintf(&fidp->path, "%s", "/");
     err = fid_to_qid(s, fidp, &qid);
-    if (err) {
+    if (err < 0) {
         err = -EINVAL;
         free_fid(s, fid);
         goto out;
     }
-
     offset += pdu_marshal(pdu, offset, "Q", &qid);
-
     err = offset;
 out:
     complete_pdu(s, pdu, err);
@@ -1192,56 +1032,36 @@
     v9fs_string_free(&aname);
 }
 
-static void v9fs_stat_post_lstat(V9fsState *s, V9fsStatState *vs, int err)
-{
-    if (err == -1) {
-        err = -errno;
-        goto out;
-    }
-
-    err = stat_to_v9stat(s, &vs->fidp->path, &vs->stbuf, &vs->v9stat);
-    if (err) {
-        goto out;
-    }
-    vs->offset += pdu_marshal(vs->pdu, vs->offset, "wS", 0, &vs->v9stat);
-    err = vs->offset;
-
-out:
-    complete_pdu(s, vs->pdu, err);
-    v9fs_stat_free(&vs->v9stat);
-    g_free(vs);
-}
-
 static void v9fs_stat(void *opaque)
 {
+    int32_t fid;
+    V9fsStat v9stat;
+    ssize_t err = 0;
+    size_t offset = 7;
+    struct stat stbuf;
+    V9fsFidState *fidp;
     V9fsPDU *pdu = opaque;
     V9fsState *s = pdu->s;
-    int32_t fid;
-    V9fsStatState *vs;
-    ssize_t err = 0;
 
-    vs = g_malloc(sizeof(*vs));
-    vs->pdu = pdu;
-    vs->offset = 7;
-
-    memset(&vs->v9stat, 0, sizeof(vs->v9stat));
-
-    pdu_unmarshal(vs->pdu, vs->offset, "d", &fid);
-
-    vs->fidp = lookup_fid(s, fid);
-    if (vs->fidp == NULL) {
+    pdu_unmarshal(pdu, offset, "d", &fid);
+    fidp = lookup_fid(s, fid);
+    if (fidp == NULL) {
         err = -ENOENT;
         goto out;
     }
-
-    err = v9fs_do_lstat(s, &vs->fidp->path, &vs->stbuf);
-    v9fs_stat_post_lstat(s, vs, err);
-    return;
-
+    err = v9fs_co_lstat(s, &fidp->path, &stbuf);
+    if (err < 0) {
+        goto out;
+    }
+    err = stat_to_v9stat(s, &fidp->path, &stbuf, &v9stat);
+    if (err < 0) {
+        goto out;
+    }
+    offset += pdu_marshal(pdu, offset, "wS", 0, &v9stat);
+    err = offset;
+    v9fs_stat_free(&v9stat);
 out:
-    complete_pdu(s, vs->pdu, err);
-    v9fs_stat_free(&vs->v9stat);
-    g_free(vs);
+    complete_pdu(s, pdu, err);
 }
 
 static void v9fs_getattr(void *opaque)
@@ -1370,171 +1190,101 @@
     complete_pdu(s, pdu, err);
 }
 
-static void v9fs_walk_complete(V9fsState *s, V9fsWalkState *vs, int err)
-{
-    complete_pdu(s, vs->pdu, err);
-
-    if (vs->nwnames && vs->nwnames <= P9_MAXWELEM) {
-        for (vs->name_idx = 0; vs->name_idx < vs->nwnames; vs->name_idx++) {
-            v9fs_string_free(&vs->wnames[vs->name_idx]);
-        }
-
-        g_free(vs->wnames);
-        g_free(vs->qids);
-    }
-}
-
-static void v9fs_walk_marshal(V9fsWalkState *vs)
+static int v9fs_walk_marshal(V9fsPDU *pdu, uint16_t nwnames, V9fsQID *qids)
 {
     int i;
-    vs->offset = 7;
-    vs->offset += pdu_marshal(vs->pdu, vs->offset, "w", vs->nwnames);
-
-    for (i = 0; i < vs->nwnames; i++) {
-        vs->offset += pdu_marshal(vs->pdu, vs->offset, "Q", &vs->qids[i]);
+    size_t offset = 7;
+    offset += pdu_marshal(pdu, offset, "w", nwnames);
+    for (i = 0; i < nwnames; i++) {
+        offset += pdu_marshal(pdu, offset, "Q", &qids[i]);
     }
-}
-
-static void v9fs_walk_post_newfid_lstat(V9fsState *s, V9fsWalkState *vs,
-                                                                int err)
-{
-    if (err == -1) {
-        free_fid(s, vs->newfidp->fid);
-        v9fs_string_free(&vs->path);
-        err = -ENOENT;
-        goto out;
-    }
-
-    stat_to_qid(&vs->stbuf, &vs->qids[vs->name_idx]);
-
-    vs->name_idx++;
-    if (vs->name_idx < vs->nwnames) {
-        v9fs_string_sprintf(&vs->path, "%s/%s", vs->newfidp->path.data,
-                                            vs->wnames[vs->name_idx].data);
-        v9fs_string_copy(&vs->newfidp->path, &vs->path);
-
-        err = v9fs_do_lstat(s, &vs->newfidp->path, &vs->stbuf);
-        v9fs_walk_post_newfid_lstat(s, vs, err);
-        return;
-    }
-
-    v9fs_string_free(&vs->path);
-    v9fs_walk_marshal(vs);
-    err = vs->offset;
-out:
-    v9fs_walk_complete(s, vs, err);
-}
-
-static void v9fs_walk_post_oldfid_lstat(V9fsState *s, V9fsWalkState *vs,
-        int err)
-{
-    if (err == -1) {
-        v9fs_string_free(&vs->path);
-        err = -ENOENT;
-        goto out;
-    }
-
-    stat_to_qid(&vs->stbuf, &vs->qids[vs->name_idx]);
-    vs->name_idx++;
-    if (vs->name_idx < vs->nwnames) {
-
-        v9fs_string_sprintf(&vs->path, "%s/%s",
-                vs->fidp->path.data, vs->wnames[vs->name_idx].data);
-        v9fs_string_copy(&vs->fidp->path, &vs->path);
-
-        err = v9fs_do_lstat(s, &vs->fidp->path, &vs->stbuf);
-        v9fs_walk_post_oldfid_lstat(s, vs, err);
-        return;
-    }
-
-    v9fs_string_free(&vs->path);
-    v9fs_walk_marshal(vs);
-    err = vs->offset;
-out:
-    v9fs_walk_complete(s, vs, err);
+    return offset;
 }
 
 static void v9fs_walk(void *opaque)
 {
+    int name_idx;
+    V9fsQID *qids = NULL;
+    int i, err = 0;
+    V9fsString path;
+    uint16_t nwnames;
+    struct stat stbuf;
+    size_t offset = 7;
+    int32_t fid, newfid;
+    V9fsString *wnames = NULL;
+    V9fsFidState *fidp;
+    V9fsFidState *newfidp;
     V9fsPDU *pdu = opaque;
     V9fsState *s = pdu->s;
-    int32_t fid, newfid;
-    V9fsWalkState *vs;
-    int err = 0;
-    int i;
 
-    vs = g_malloc(sizeof(*vs));
-    vs->pdu = pdu;
-    vs->wnames = NULL;
-    vs->qids = NULL;
-    vs->offset = 7;
+    offset += pdu_unmarshal(pdu, offset, "ddw", &fid,
+                            &newfid, &nwnames);
 
-    vs->offset += pdu_unmarshal(vs->pdu, vs->offset, "ddw", &fid,
-                                            &newfid, &vs->nwnames);
-
-    if (vs->nwnames && vs->nwnames <= P9_MAXWELEM) {
-        vs->wnames = g_malloc0(sizeof(vs->wnames[0]) * vs->nwnames);
-
-        vs->qids = g_malloc0(sizeof(vs->qids[0]) * vs->nwnames);
-
-        for (i = 0; i < vs->nwnames; i++) {
-            vs->offset += pdu_unmarshal(vs->pdu, vs->offset, "s",
-                                            &vs->wnames[i]);
+    if (nwnames && nwnames <= P9_MAXWELEM) {
+        wnames = g_malloc0(sizeof(wnames[0]) * nwnames);
+        qids   = g_malloc0(sizeof(qids[0]) * nwnames);
+        for (i = 0; i < nwnames; i++) {
+            offset += pdu_unmarshal(pdu, offset, "s", &wnames[i]);
         }
-    } else if (vs->nwnames > P9_MAXWELEM) {
+
+    } else if (nwnames > P9_MAXWELEM) {
         err = -EINVAL;
         goto out;
     }
-
-    vs->fidp = lookup_fid(s, fid);
-    if (vs->fidp == NULL) {
+    fidp = lookup_fid(s, fid);
+    if (fidp == NULL) {
         err = -ENOENT;
         goto out;
     }
-
-    /* FIXME: is this really valid? */
     if (fid == newfid) {
+        BUG_ON(fidp->fid_type != P9_FID_NONE);
+        v9fs_string_init(&path);
+        for (name_idx = 0; name_idx < nwnames; name_idx++) {
+            v9fs_string_sprintf(&path, "%s/%s",
+                                fidp->path.data, wnames[name_idx].data);
+            v9fs_string_copy(&fidp->path, &path);
 
-        BUG_ON(vs->fidp->fid_type != P9_FID_NONE);
-        v9fs_string_init(&vs->path);
-        vs->name_idx = 0;
-
-        if (vs->name_idx < vs->nwnames) {
-            v9fs_string_sprintf(&vs->path, "%s/%s",
-                vs->fidp->path.data, vs->wnames[vs->name_idx].data);
-            v9fs_string_copy(&vs->fidp->path, &vs->path);
-
-            err = v9fs_do_lstat(s, &vs->fidp->path, &vs->stbuf);
-            v9fs_walk_post_oldfid_lstat(s, vs, err);
-            return;
+            err = v9fs_co_lstat(s, &fidp->path, &stbuf);
+            if (err < 0) {
+                v9fs_string_free(&path);
+                goto out;
+            }
+            stat_to_qid(&stbuf, &qids[name_idx]);
         }
+        v9fs_string_free(&path);
     } else {
-        vs->newfidp = alloc_fid(s, newfid);
-        if (vs->newfidp == NULL) {
+        newfidp = alloc_fid(s, newfid);
+        if (newfidp == NULL) {
             err = -EINVAL;
             goto out;
         }
-
-        vs->newfidp->uid = vs->fidp->uid;
-        v9fs_string_init(&vs->path);
-        vs->name_idx = 0;
-        v9fs_string_copy(&vs->newfidp->path, &vs->fidp->path);
-
-        if (vs->name_idx < vs->nwnames) {
-            v9fs_string_sprintf(&vs->path, "%s/%s", vs->newfidp->path.data,
-                                vs->wnames[vs->name_idx].data);
-            v9fs_string_copy(&vs->newfidp->path, &vs->path);
-
-            err = v9fs_do_lstat(s, &vs->newfidp->path, &vs->stbuf);
-            v9fs_walk_post_newfid_lstat(s, vs, err);
-            return;
+        newfidp->uid = fidp->uid;
+        v9fs_string_init(&path);
+        v9fs_string_copy(&newfidp->path, &fidp->path);
+        for (name_idx = 0; name_idx < nwnames; name_idx++) {
+            v9fs_string_sprintf(&path, "%s/%s", newfidp->path.data,
+                                wnames[name_idx].data);
+            v9fs_string_copy(&newfidp->path, &path);
+            err = v9fs_co_lstat(s, &newfidp->path, &stbuf);
+            if (err < 0) {
+                free_fid(s, newfidp->fid);
+                v9fs_string_free(&path);
+                goto out;
+            }
+            stat_to_qid(&stbuf, &qids[name_idx]);
         }
+        v9fs_string_free(&path);
     }
-
-    v9fs_walk_marshal(vs);
-    err = vs->offset;
+    err = v9fs_walk_marshal(pdu, nwnames, qids);
 out:
-    v9fs_walk_complete(s, vs, err);
+    complete_pdu(s, pdu, err);
+    if (nwnames && nwnames <= P9_MAXWELEM) {
+        for (name_idx = 0; name_idx < nwnames; name_idx++) {
+            v9fs_string_free(&wnames[name_idx]);
+        }
+        g_free(wnames);
+        g_free(qids);
+    }
 }
 
 static int32_t get_iounit(V9fsState *s, V9fsString *name)
@@ -1546,467 +1296,323 @@
      * iounit should be multiples of f_bsize (host filesystem block size
      * and as well as less than (client msize - P9_IOHDRSZ))
      */
-    if (!v9fs_do_statfs(s, name, &stbuf)) {
+    if (!v9fs_co_statfs(s, name, &stbuf)) {
         iounit = stbuf.f_bsize;
         iounit *= (s->msize - P9_IOHDRSZ)/stbuf.f_bsize;
     }
-
     if (!iounit) {
         iounit = s->msize - P9_IOHDRSZ;
     }
     return iounit;
 }
 
-static void v9fs_open_post_opendir(V9fsState *s, V9fsOpenState *vs, int err)
-{
-    if (vs->fidp->fs.dir == NULL) {
-        err = -errno;
-        goto out;
-    }
-    vs->fidp->fid_type = P9_FID_DIR;
-    vs->offset += pdu_marshal(vs->pdu, vs->offset, "Qd", &vs->qid, 0);
-    err = vs->offset;
-out:
-    complete_pdu(s, vs->pdu, err);
-    g_free(vs);
-
-}
-
-static void v9fs_open_post_getiounit(V9fsState *s, V9fsOpenState *vs)
-{
-    int err;
-    vs->offset += pdu_marshal(vs->pdu, vs->offset, "Qd", &vs->qid, vs->iounit);
-    err = vs->offset;
-    complete_pdu(s, vs->pdu, err);
-    g_free(vs);
-}
-
-static void v9fs_open_post_open(V9fsState *s, V9fsOpenState *vs, int err)
-{
-    if (vs->fidp->fs.fd == -1) {
-        err = -errno;
-        goto out;
-    }
-    vs->fidp->fid_type = P9_FID_FILE;
-    vs->iounit = get_iounit(s, &vs->fidp->path);
-    v9fs_open_post_getiounit(s, vs);
-    return;
-out:
-    complete_pdu(s, vs->pdu, err);
-    g_free(vs);
-}
-
-static void v9fs_open_post_lstat(V9fsState *s, V9fsOpenState *vs, int err)
+static void v9fs_open(void *opaque)
 {
     int flags;
+    int iounit;
+    int32_t fid;
+    int32_t mode;
+    V9fsQID qid;
+    ssize_t err = 0;
+    size_t offset = 7;
+    struct stat stbuf;
+    V9fsFidState *fidp;
+    V9fsPDU *pdu = opaque;
+    V9fsState *s = pdu->s;
 
-    if (err) {
-        err = -errno;
+    if (s->proto_version == V9FS_PROTO_2000L) {
+        pdu_unmarshal(pdu, offset, "dd", &fid, &mode);
+    } else {
+        pdu_unmarshal(pdu, offset, "db", &fid, &mode);
+    }
+    fidp = lookup_fid(s, fid);
+    if (fidp == NULL) {
+        err = -ENOENT;
         goto out;
     }
+    BUG_ON(fidp->fid_type != P9_FID_NONE);
 
-    stat_to_qid(&vs->stbuf, &vs->qid);
-
-    if (S_ISDIR(vs->stbuf.st_mode)) {
-        vs->fidp->fs.dir = v9fs_do_opendir(s, &vs->fidp->path);
-        v9fs_open_post_opendir(s, vs, err);
+    err = v9fs_co_lstat(s, &fidp->path, &stbuf);
+    if (err < 0) {
+        goto out;
+    }
+    stat_to_qid(&stbuf, &qid);
+    if (S_ISDIR(stbuf.st_mode)) {
+        err = v9fs_co_opendir(s, fidp);
+        if (err < 0) {
+            goto out;
+        }
+        fidp->fid_type = P9_FID_DIR;
+        offset += pdu_marshal(pdu, offset, "Qd", &qid, 0);
+        err = offset;
     } else {
         if (s->proto_version == V9FS_PROTO_2000L) {
-            flags = vs->mode;
+            flags = mode;
             flags &= ~(O_NOCTTY | O_ASYNC | O_CREAT);
             /* Ignore direct disk access hint until the server supports it. */
             flags &= ~O_DIRECT;
         } else {
-            flags = omode_to_uflags(vs->mode);
+            flags = omode_to_uflags(mode);
         }
-        vs->fidp->fs.fd = v9fs_do_open(s, &vs->fidp->path, flags);
-        v9fs_open_post_open(s, vs, err);
+        err = v9fs_co_open(s, fidp, flags);
+        if (err < 0) {
+            goto out;
+        }
+        fidp->fid_type = P9_FID_FILE;
+        iounit = get_iounit(s, &fidp->path);
+        offset += pdu_marshal(pdu, offset, "Qd", &qid, iounit);
+        err = offset;
     }
-    return;
-out:
-    complete_pdu(s, vs->pdu, err);
-    g_free(vs);
-}
-
-static void v9fs_open(void *opaque)
-{
-    V9fsPDU *pdu = opaque;
-    V9fsState *s = pdu->s;
-    int32_t fid;
-    V9fsOpenState *vs;
-    ssize_t err = 0;
-
-    vs = g_malloc(sizeof(*vs));
-    vs->pdu = pdu;
-    vs->offset = 7;
-    vs->mode = 0;
-
-    if (s->proto_version == V9FS_PROTO_2000L) {
-        pdu_unmarshal(vs->pdu, vs->offset, "dd", &fid, &vs->mode);
-    } else {
-        pdu_unmarshal(vs->pdu, vs->offset, "db", &fid, &vs->mode);
-    }
-
-    vs->fidp = lookup_fid(s, fid);
-    if (vs->fidp == NULL) {
-        err = -ENOENT;
-        goto out;
-    }
-
-    BUG_ON(vs->fidp->fid_type != P9_FID_NONE);
-
-    err = v9fs_do_lstat(s, &vs->fidp->path, &vs->stbuf);
-
-    v9fs_open_post_lstat(s, vs, err);
-    return;
 out:
     complete_pdu(s, pdu, err);
-    g_free(vs);
-}
-
-static void v9fs_post_lcreate(V9fsState *s, V9fsLcreateState *vs, int err)
-{
-    if (err == 0) {
-        v9fs_string_copy(&vs->fidp->path, &vs->fullname);
-        stat_to_qid(&vs->stbuf, &vs->qid);
-        vs->offset += pdu_marshal(vs->pdu, vs->offset, "Qd", &vs->qid,
-                vs->iounit);
-        err = vs->offset;
-    } else {
-        vs->fidp->fid_type = P9_FID_NONE;
-        err = -errno;
-        if (vs->fidp->fs.fd > 0) {
-            close(vs->fidp->fs.fd);
-        }
-    }
-
-    complete_pdu(s, vs->pdu, err);
-    v9fs_string_free(&vs->name);
-    v9fs_string_free(&vs->fullname);
-    g_free(vs);
-}
-
-static void v9fs_lcreate_post_get_iounit(V9fsState *s, V9fsLcreateState *vs,
-        int err)
-{
-    if (err) {
-        err = -errno;
-        goto out;
-    }
-    err = v9fs_do_lstat(s, &vs->fullname, &vs->stbuf);
-
-out:
-    v9fs_post_lcreate(s, vs, err);
-}
-
-static void v9fs_lcreate_post_do_open2(V9fsState *s, V9fsLcreateState *vs,
-        int err)
-{
-    if (vs->fidp->fs.fd == -1) {
-        err = -errno;
-        goto out;
-    }
-    vs->fidp->fid_type = P9_FID_FILE;
-    vs->iounit =  get_iounit(s, &vs->fullname);
-    v9fs_lcreate_post_get_iounit(s, vs, err);
-    return;
-
-out:
-    v9fs_post_lcreate(s, vs, err);
 }
 
 static void v9fs_lcreate(void *opaque)
 {
-    V9fsPDU *pdu = opaque;
-    V9fsState *s = pdu->s;
     int32_t dfid, flags, mode;
     gid_t gid;
-    V9fsLcreateState *vs;
     ssize_t err = 0;
+    ssize_t offset = 7;
+    V9fsString fullname;
+    V9fsString name;
+    V9fsFidState *fidp;
+    struct stat stbuf;
+    V9fsQID qid;
+    int32_t iounit;
+    V9fsPDU *pdu = opaque;
 
-    vs = g_malloc(sizeof(*vs));
-    vs->pdu = pdu;
-    vs->offset = 7;
+    v9fs_string_init(&fullname);
+    pdu_unmarshal(pdu, offset, "dsddd", &dfid, &name, &flags,
+                  &mode, &gid);
 
-    v9fs_string_init(&vs->fullname);
-
-    pdu_unmarshal(vs->pdu, vs->offset, "dsddd", &dfid, &vs->name, &flags,
-            &mode, &gid);
-
-    vs->fidp = lookup_fid(s, dfid);
-    if (vs->fidp == NULL) {
+    fidp = lookup_fid(pdu->s, dfid);
+    if (fidp == NULL) {
         err = -ENOENT;
         goto out;
     }
-
-    v9fs_string_sprintf(&vs->fullname, "%s/%s", vs->fidp->path.data,
-             vs->name.data);
+    v9fs_string_sprintf(&fullname, "%s/%s", fidp->path.data, name.data);
 
     /* Ignore direct disk access hint until the server supports it. */
     flags &= ~O_DIRECT;
 
-    vs->fidp->fs.fd = v9fs_do_open2(s, vs->fullname.data, vs->fidp->uid,
-            gid, flags, mode);
-    v9fs_lcreate_post_do_open2(s, vs, err);
-    return;
-
-out:
-    complete_pdu(s, vs->pdu, err);
-    v9fs_string_free(&vs->name);
-    g_free(vs);
-}
-
-static void v9fs_post_do_fsync(V9fsState *s, V9fsPDU *pdu, int err)
-{
-    if (err == -1) {
-        err = -errno;
+    err = v9fs_co_open2(pdu->s, fidp, fullname.data, gid, flags, mode);
+    if (err < 0) {
+        goto out;
     }
-    complete_pdu(s, pdu, err);
+    fidp->fid_type = P9_FID_FILE;
+    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);
+        }
+        goto out;
+    }
+    v9fs_string_copy(&fidp->path, &fullname);
+    stat_to_qid(&stbuf, &qid);
+    offset += pdu_marshal(pdu, offset, "Qd", &qid, iounit);
+    err = offset;
+out:
+    complete_pdu(pdu->s, pdu, err);
+    v9fs_string_free(&name);
+    v9fs_string_free(&fullname);
 }
 
 static void v9fs_fsync(void *opaque)
 {
-    V9fsPDU *pdu = opaque;
-    V9fsState *s = pdu->s;
+    int err;
     int32_t fid;
+    int datasync;
     size_t offset = 7;
     V9fsFidState *fidp;
-    int datasync;
-    int err;
+    V9fsPDU *pdu = opaque;
+    V9fsState *s = pdu->s;
 
     pdu_unmarshal(pdu, offset, "dd", &fid, &datasync);
     fidp = lookup_fid(s, fid);
     if (fidp == NULL) {
         err = -ENOENT;
-        v9fs_post_do_fsync(s, pdu, err);
-        return;
+        goto out;
     }
-    err = v9fs_do_fsync(s, fidp->fs.fd, datasync);
-    v9fs_post_do_fsync(s, pdu, err);
+    err = v9fs_co_fsync(s, fidp, datasync);
+    if (!err) {
+        err = offset;
+    }
+out:
+    complete_pdu(s, pdu, err);
 }
 
 static void v9fs_clunk(void *opaque)
 {
-    V9fsPDU *pdu = opaque;
-    V9fsState *s = pdu->s;
+    int err;
     int32_t fid;
     size_t offset = 7;
-    int err;
+    V9fsPDU *pdu = opaque;
+    V9fsState *s = pdu->s;
 
     pdu_unmarshal(pdu, offset, "d", &fid);
-
     err = free_fid(s, fid);
     if (err < 0) {
         goto out;
     }
-
-    offset = 7;
     err = offset;
 out:
     complete_pdu(s, pdu, err);
 }
 
-static void v9fs_read_post_readdir(V9fsState *, V9fsReadState *, ssize_t);
-
-static void v9fs_read_post_seekdir(V9fsState *s, V9fsReadState *vs, ssize_t err)
+static int v9fs_xattr_read(V9fsState *s, V9fsPDU *pdu,
+                           V9fsFidState *fidp, int64_t off, int32_t max_count)
 {
-    if (err) {
-        goto out;
-    }
-    vs->offset += pdu_marshal(vs->pdu, vs->offset, "d", vs->count);
-    vs->offset += vs->count;
-    err = vs->offset;
-out:
-    complete_pdu(s, vs->pdu, err);
-    v9fs_stat_free(&vs->v9stat);
-    v9fs_string_free(&vs->name);
-    g_free(vs);
-    return;
-}
-
-static void v9fs_read_post_dir_lstat(V9fsState *s, V9fsReadState *vs,
-                                    ssize_t err)
-{
-    if (err) {
-        err = -errno;
-        goto out;
-    }
-    err = stat_to_v9stat(s, &vs->name, &vs->stbuf, &vs->v9stat);
-    if (err) {
-        goto out;
-    }
-
-    vs->len = pdu_marshal(vs->pdu, vs->offset + 4 + vs->count, "S",
-                            &vs->v9stat);
-    if ((vs->len != (vs->v9stat.size + 2)) ||
-            ((vs->count + vs->len) > vs->max_count)) {
-        v9fs_do_seekdir(s, vs->fidp->fs.dir, vs->dir_pos);
-        v9fs_read_post_seekdir(s, vs, err);
-        return;
-    }
-    vs->count += vs->len;
-    v9fs_stat_free(&vs->v9stat);
-    v9fs_string_free(&vs->name);
-    vs->dir_pos = vs->dent->d_off;
-    v9fs_co_readdir(s, vs->fidp, &vs->dent);
-    v9fs_read_post_readdir(s, vs, err);
-    return;
-out:
-    v9fs_do_seekdir(s, vs->fidp->fs.dir, vs->dir_pos);
-    v9fs_read_post_seekdir(s, vs, err);
-    return;
-
-}
-
-static void v9fs_read_post_readdir(V9fsState *s, V9fsReadState *vs, ssize_t err)
-{
-    if (vs->dent) {
-        memset(&vs->v9stat, 0, sizeof(vs->v9stat));
-        v9fs_string_init(&vs->name);
-        v9fs_string_sprintf(&vs->name, "%s/%s", vs->fidp->path.data,
-                            vs->dent->d_name);
-        err = v9fs_do_lstat(s, &vs->name, &vs->stbuf);
-        v9fs_read_post_dir_lstat(s, vs, err);
-        return;
-    }
-
-    vs->offset += pdu_marshal(vs->pdu, vs->offset, "d", vs->count);
-    vs->offset += vs->count;
-    err = vs->offset;
-    complete_pdu(s, vs->pdu, err);
-    g_free(vs);
-    return;
-}
-
-static void v9fs_read_post_telldir(V9fsState *s, V9fsReadState *vs, ssize_t err)
-{
-    v9fs_co_readdir(s, vs->fidp, &vs->dent);
-    v9fs_read_post_readdir(s, vs, err);
-    return;
-}
-
-static void v9fs_read_post_rewinddir(V9fsState *s, V9fsReadState *vs,
-                                       ssize_t err)
-{
-    vs->dir_pos = v9fs_do_telldir(s, vs->fidp->fs.dir);
-    v9fs_read_post_telldir(s, vs, err);
-    return;
-}
-
-static void v9fs_read_post_preadv(V9fsState *s, V9fsReadState *vs, ssize_t err)
-{
-    if (err  < 0) {
-        /* IO error return the error */
-        err = -errno;
-        goto out;
-    }
-    vs->total += vs->len;
-    vs->sg = adjust_sg(vs->sg, vs->len, &vs->cnt);
-    if (vs->total < vs->count && vs->len > 0) {
-        do {
-            if (0) {
-                print_sg(vs->sg, vs->cnt);
-            }
-            vs->len = v9fs_do_preadv(s, vs->fidp->fs.fd, vs->sg, vs->cnt,
-                      vs->off);
-            if (vs->len > 0) {
-                vs->off += vs->len;
-            }
-        } while (vs->len == -1 && errno == EINTR);
-        if (vs->len == -1) {
-            err  = -errno;
-        }
-        v9fs_read_post_preadv(s, vs, err);
-        return;
-    }
-    vs->offset += pdu_marshal(vs->pdu, vs->offset, "d", vs->total);
-    vs->offset += vs->count;
-    err = vs->offset;
-
-out:
-    complete_pdu(s, vs->pdu, err);
-    g_free(vs);
-}
-
-static void v9fs_xattr_read(V9fsState *s, V9fsReadState *vs)
-{
-    ssize_t err = 0;
+    size_t offset = 7;
     int read_count;
     int64_t xattr_len;
 
-    xattr_len = vs->fidp->fs.xattr.len;
-    read_count = xattr_len - vs->off;
-    if (read_count > vs->count) {
-        read_count = vs->count;
+    xattr_len = fidp->fs.xattr.len;
+    read_count = xattr_len - off;
+    if (read_count > max_count) {
+        read_count = max_count;
     } else if (read_count < 0) {
         /*
          * read beyond XATTR value
          */
         read_count = 0;
     }
-    vs->offset += pdu_marshal(vs->pdu, vs->offset, "d", read_count);
-    vs->offset += pdu_pack(vs->pdu, vs->offset,
-                           ((char *)vs->fidp->fs.xattr.value) + vs->off,
-                           read_count);
-    err = vs->offset;
-    complete_pdu(s, vs->pdu, err);
-    g_free(vs);
+    offset += pdu_marshal(pdu, offset, "d", read_count);
+    offset += pdu_pack(pdu, offset,
+                       ((char *)fidp->fs.xattr.value) + off,
+                       read_count);
+    return offset;
+}
+
+static int v9fs_do_readdir_with_stat(V9fsState *s, V9fsPDU *pdu,
+                                     V9fsFidState *fidp, int32_t max_count)
+{
+    V9fsString name;
+    V9fsStat v9stat;
+    int len, err = 0;
+    int32_t count = 0;
+    struct stat stbuf;
+    off_t saved_dir_pos;
+    struct dirent *dent, *result;
+
+    /* save the directory position */
+    saved_dir_pos = v9fs_co_telldir(s, fidp);
+    if (saved_dir_pos < 0) {
+        return saved_dir_pos;
+    }
+
+    dent = g_malloc(sizeof(struct dirent));
+
+    while (1) {
+        v9fs_string_init(&name);
+        err = v9fs_co_readdir_r(s, fidp, dent, &result);
+        if (err || !result) {
+            break;
+        }
+        v9fs_string_sprintf(&name, "%s/%s", fidp->path.data, dent->d_name);
+        err = v9fs_co_lstat(s, &name, &stbuf);
+        if (err < 0) {
+            goto out;
+        }
+        err = stat_to_v9stat(s, &name, &stbuf, &v9stat);
+        if (err < 0) {
+            goto out;
+        }
+        /* 11 = 7 + 4 (7 = start offset, 4 = space for storing count) */
+        len = pdu_marshal(pdu, 11 + count, "S", &v9stat);
+        if ((len != (v9stat.size + 2)) || ((count + len) > max_count)) {
+            /* Ran out of buffer. Set dir back to old position and return */
+            v9fs_co_seekdir(s, fidp, saved_dir_pos);
+            v9fs_stat_free(&v9stat);
+            v9fs_string_free(&name);
+            g_free(dent);
+            return count;
+        }
+        count += len;
+        v9fs_stat_free(&v9stat);
+        v9fs_string_free(&name);
+        saved_dir_pos = dent->d_off;
+    }
+out:
+    g_free(dent);
+    v9fs_string_free(&name);
+    if (err < 0) {
+        return err;
+    }
+    return count;
 }
 
 static void v9fs_read(void *opaque)
 {
+    int32_t fid;
+    int64_t off;
+    ssize_t err = 0;
+    int32_t count = 0;
+    size_t offset = 7;
+    int32_t max_count;
+    V9fsFidState *fidp;
     V9fsPDU *pdu = opaque;
     V9fsState *s = pdu->s;
-    int32_t fid;
-    V9fsReadState *vs;
-    ssize_t err = 0;
 
-    vs = g_malloc(sizeof(*vs));
-    vs->pdu = pdu;
-    vs->offset = 7;
-    vs->total = 0;
-    vs->len = 0;
-    vs->count = 0;
-
-    pdu_unmarshal(vs->pdu, vs->offset, "dqd", &fid, &vs->off, &vs->count);
-
-    vs->fidp = lookup_fid(s, fid);
-    if (vs->fidp == NULL) {
+    pdu_unmarshal(pdu, offset, "dqd", &fid, &off, &max_count);
+    fidp = lookup_fid(s, fid);
+    if (fidp == NULL) {
         err = -EINVAL;
         goto out;
     }
+    if (fidp->fid_type == P9_FID_DIR) {
 
-    if (vs->fidp->fid_type == P9_FID_DIR) {
-        vs->max_count = vs->count;
-        vs->count = 0;
-        if (vs->off == 0) {
-            v9fs_do_rewinddir(s, vs->fidp->fs.dir);
+        if (off == 0) {
+            v9fs_co_rewinddir(s, fidp);
         }
-        v9fs_read_post_rewinddir(s, vs, err);
-        return;
-    } else if (vs->fidp->fid_type == P9_FID_FILE) {
-        vs->sg = vs->iov;
-        pdu_marshal(vs->pdu, vs->offset + 4, "v", vs->sg, &vs->cnt);
-        vs->sg = cap_sg(vs->sg, vs->count, &vs->cnt);
-        if (vs->total <= vs->count) {
-            vs->len = v9fs_do_preadv(s, vs->fidp->fs.fd, vs->sg, vs->cnt,
-                                    vs->off);
-            if (vs->len > 0) {
-                vs->off += vs->len;
+        count = v9fs_do_readdir_with_stat(s, pdu, fidp, max_count);
+        if (count < 0) {
+            err = count;
+            goto out;
+        }
+        err = offset;
+        err += pdu_marshal(pdu, offset, "d", count);
+        err += count;
+    } else if (fidp->fid_type == P9_FID_FILE) {
+        int32_t cnt;
+        int32_t len;
+        struct iovec *sg;
+        struct iovec iov[128]; /* FIXME: bad, bad, bad */
+
+        sg = iov;
+        pdu_marshal(pdu, offset + 4, "v", sg, &cnt);
+        sg = cap_sg(sg, max_count, &cnt);
+        do {
+            if (0) {
+                print_sg(sg, cnt);
             }
-            err = vs->len;
-            v9fs_read_post_preadv(s, vs, err);
-        }
-        return;
-    } else if (vs->fidp->fid_type == P9_FID_XATTR) {
-        v9fs_xattr_read(s, vs);
-        return;
+            /* Loop in case of EINTR */
+            do {
+                len = v9fs_co_preadv(s, fidp, sg, cnt, off);
+                if (len >= 0) {
+                    off   += len;
+                    count += len;
+                }
+            } while (len == -EINTR);
+            if (len < 0) {
+                /* IO error return the error */
+                err = len;
+                goto out;
+            }
+            sg = adjust_sg(sg, len, &cnt);
+        } while (count < max_count && len > 0);
+        err = offset;
+        err += pdu_marshal(pdu, offset, "d", count);
+        err += count;
+    } else if (fidp->fid_type == P9_FID_XATTR) {
+        err = v9fs_xattr_read(s, pdu, fidp, off, max_count);
     } else {
         err = -EINVAL;
     }
 out:
     complete_pdu(s, pdu, err);
-    g_free(vs);
 }
 
 static size_t v9fs_readdir_data_size(V9fsString *name)
@@ -2027,16 +1633,19 @@
     int len, err = 0;
     int32_t count = 0;
     off_t saved_dir_pos;
-    struct dirent *dent;
+    struct dirent *dent, *result;
 
     /* save the directory position */
     saved_dir_pos = v9fs_co_telldir(s, fidp);
     if (saved_dir_pos < 0) {
         return saved_dir_pos;
     }
+
+    dent = g_malloc(sizeof(struct dirent));
+
     while (1) {
-        err = v9fs_co_readdir(s, fidp, &dent);
-        if (err || !dent) {
+        err = v9fs_co_readdir_r(s, fidp, dent, &result);
+        if (err || !result) {
             break;
         }
         v9fs_string_init(&name);
@@ -2045,6 +1654,7 @@
             /* Ran out of buffer. Set dir back to old position and return */
             v9fs_co_seekdir(s, fidp, saved_dir_pos);
             v9fs_string_free(&name);
+            g_free(dent);
             return count;
         }
         /*
@@ -2066,6 +1676,7 @@
         v9fs_string_free(&name);
         saved_dir_pos = dent->d_off;
     }
+    g_free(dent);
     if (err < 0) {
         return err;
     }
@@ -2107,51 +1718,21 @@
     complete_pdu(s, pdu, retval);
 }
 
-static void v9fs_write_post_pwritev(V9fsState *s, V9fsWriteState *vs,
-                                   ssize_t err)
-{
-    if (err  < 0) {
-        /* IO error return the error */
-        err = -errno;
-        goto out;
-    }
-    vs->total += vs->len;
-    vs->sg = adjust_sg(vs->sg, vs->len, &vs->cnt);
-    if (vs->total < vs->count && vs->len > 0) {
-        do {
-            if (0) {
-                print_sg(vs->sg, vs->cnt);
-            }
-            vs->len = v9fs_do_pwritev(s, vs->fidp->fs.fd, vs->sg, vs->cnt,
-                      vs->off);
-            if (vs->len > 0) {
-                vs->off += vs->len;
-            }
-        } while (vs->len == -1 && errno == EINTR);
-        if (vs->len == -1) {
-            err  = -errno;
-        }
-        v9fs_write_post_pwritev(s, vs, err);
-        return;
-    }
-    vs->offset += pdu_marshal(vs->pdu, vs->offset, "d", vs->total);
-    err = vs->offset;
-out:
-    complete_pdu(s, vs->pdu, err);
-    g_free(vs);
-}
-
-static void v9fs_xattr_write(V9fsState *s, V9fsWriteState *vs)
+static int v9fs_xattr_write(V9fsState *s, V9fsPDU *pdu, V9fsFidState *fidp,
+                            int64_t off, int32_t count,
+                            struct iovec *sg, int cnt)
 {
     int i, to_copy;
     ssize_t err = 0;
     int write_count;
     int64_t xattr_len;
+    size_t offset = 7;
 
-    xattr_len = vs->fidp->fs.xattr.len;
-    write_count = xattr_len - vs->off;
-    if (write_count > vs->count) {
-        write_count = vs->count;
+
+    xattr_len = fidp->fs.xattr.len;
+    write_count = xattr_len - off;
+    if (write_count > count) {
+        write_count = count;
     } else if (write_count < 0) {
         /*
          * write beyond XATTR value len specified in
@@ -2160,225 +1741,161 @@
         err = -ENOSPC;
         goto out;
     }
-    vs->offset += pdu_marshal(vs->pdu, vs->offset, "d", write_count);
-    err = vs->offset;
-    vs->fidp->fs.xattr.copied_len += write_count;
+    offset += pdu_marshal(pdu, offset, "d", write_count);
+    err = offset;
+    fidp->fs.xattr.copied_len += write_count;
     /*
      * Now copy the content from sg list
      */
-    for (i = 0; i < vs->cnt; i++) {
-        if (write_count > vs->sg[i].iov_len) {
-            to_copy = vs->sg[i].iov_len;
+    for (i = 0; i < cnt; i++) {
+        if (write_count > sg[i].iov_len) {
+            to_copy = sg[i].iov_len;
         } else {
             to_copy = write_count;
         }
-        memcpy((char *)vs->fidp->fs.xattr.value + vs->off,
-               vs->sg[i].iov_base, to_copy);
+        memcpy((char *)fidp->fs.xattr.value + off, sg[i].iov_base, to_copy);
         /* updating vs->off since we are not using below */
-        vs->off += to_copy;
+        off += to_copy;
         write_count -= to_copy;
     }
 out:
-    complete_pdu(s, vs->pdu, err);
-    g_free(vs);
+    return err;
 }
 
 static void v9fs_write(void *opaque)
 {
+    int cnt;
+    ssize_t err;
+    int32_t fid;
+    int64_t off;
+    int32_t count;
+    int32_t len = 0;
+    int32_t total = 0;
+    size_t offset = 7;
+    V9fsFidState *fidp;
+    struct iovec iov[128]; /* FIXME: bad, bad, bad */
+    struct iovec *sg = iov;
     V9fsPDU *pdu = opaque;
     V9fsState *s = pdu->s;
-    int32_t fid;
-    V9fsWriteState *vs;
-    ssize_t err;
 
-    vs = g_malloc(sizeof(*vs));
-
-    vs->pdu = pdu;
-    vs->offset = 7;
-    vs->sg = vs->iov;
-    vs->total = 0;
-    vs->len = 0;
-
-    pdu_unmarshal(vs->pdu, vs->offset, "dqdv", &fid, &vs->off, &vs->count,
-                  vs->sg, &vs->cnt);
-
-    vs->fidp = lookup_fid(s, fid);
-    if (vs->fidp == NULL) {
+    pdu_unmarshal(pdu, offset, "dqdv", &fid, &off, &count, sg, &cnt);
+    fidp = lookup_fid(s, fid);
+    if (fidp == NULL) {
         err = -EINVAL;
         goto out;
     }
-
-    if (vs->fidp->fid_type == P9_FID_FILE) {
-        if (vs->fidp->fs.fd == -1) {
+    if (fidp->fid_type == P9_FID_FILE) {
+        if (fidp->fs.fd == -1) {
             err = -EINVAL;
             goto out;
         }
-    } else if (vs->fidp->fid_type == P9_FID_XATTR) {
+    } else if (fidp->fid_type == P9_FID_XATTR) {
         /*
          * setxattr operation
          */
-        v9fs_xattr_write(s, vs);
-        return;
+        err = v9fs_xattr_write(s, pdu, fidp, off, count, sg, cnt);
+        goto out;
     } else {
         err = -EINVAL;
         goto out;
     }
-    vs->sg = cap_sg(vs->sg, vs->count, &vs->cnt);
-    if (vs->total <= vs->count) {
-        vs->len = v9fs_do_pwritev(s, vs->fidp->fs.fd, vs->sg, vs->cnt, vs->off);
-        if (vs->len > 0) {
-            vs->off += vs->len;
+    sg = cap_sg(sg, count, &cnt);
+    do {
+        if (0) {
+            print_sg(sg, cnt);
         }
-        err = vs->len;
-        v9fs_write_post_pwritev(s, vs, err);
-    }
-    return;
+        /* Loop in case of EINTR */
+        do {
+            len = v9fs_co_pwritev(s, fidp, sg, cnt, off);
+            if (len >= 0) {
+                off   += len;
+                total += len;
+            }
+        } while (len == -EINTR);
+        if (len < 0) {
+            /* IO error return the error */
+            err = len;
+            goto out;
+        }
+        sg = adjust_sg(sg, len, &cnt);
+    } while (total < count && len > 0);
+    offset += pdu_marshal(pdu, offset, "d", total);
+    err = offset;
 out:
-    complete_pdu(s, vs->pdu, err);
-    g_free(vs);
+    complete_pdu(s, pdu, err);
 }
 
-static void v9fs_create_post_getiounit(V9fsState *s, V9fsCreateState *vs)
+static void v9fs_create(void *opaque)
 {
-    int err;
-    v9fs_string_copy(&vs->fidp->path, &vs->fullname);
-    stat_to_qid(&vs->stbuf, &vs->qid);
+    int32_t fid;
+    int err = 0;
+    size_t offset = 7;
+    V9fsFidState *fidp;
+    V9fsQID qid;
+    int32_t perm;
+    int8_t mode;
+    struct stat stbuf;
+    V9fsString name;
+    V9fsString extension;
+    V9fsString fullname;
+    int iounit;
+    V9fsPDU *pdu = opaque;
 
-    vs->offset += pdu_marshal(vs->pdu, vs->offset, "Qd", &vs->qid, vs->iounit);
-    err = vs->offset;
+    v9fs_string_init(&fullname);
 
-    complete_pdu(s, vs->pdu, err);
-    v9fs_string_free(&vs->name);
-    v9fs_string_free(&vs->extension);
-    v9fs_string_free(&vs->fullname);
-    g_free(vs);
-}
+    pdu_unmarshal(pdu, offset, "dsdbs", &fid, &name,
+                  &perm, &mode, &extension);
 
-static void v9fs_post_create(V9fsState *s, V9fsCreateState *vs, int err)
-{
-    if (err == 0) {
-        vs->iounit = get_iounit(s, &vs->fidp->path);
-        v9fs_create_post_getiounit(s, vs);
-        return;
-    }
-
-    complete_pdu(s, vs->pdu, err);
-    v9fs_string_free(&vs->name);
-    v9fs_string_free(&vs->extension);
-    v9fs_string_free(&vs->fullname);
-    g_free(vs);
-}
-
-static void v9fs_create_post_perms(V9fsState *s, V9fsCreateState *vs, int err)
-{
-    if (err) {
-        err = -errno;
-    }
-    v9fs_post_create(s, vs, err);
-}
-
-static void v9fs_create_post_opendir(V9fsState *s, V9fsCreateState *vs,
-                                                                    int err)
-{
-    if (!vs->fidp->fs.dir) {
-        err = -errno;
-    }
-    vs->fidp->fid_type = P9_FID_DIR;
-    v9fs_post_create(s, vs, err);
-}
-
-static void v9fs_create_post_dir_lstat(V9fsState *s, V9fsCreateState *vs,
-                                                                    int err)
-{
-    if (err) {
-        err = -errno;
+    fidp = lookup_fid(pdu->s, fid);
+    if (fidp == NULL) {
+        err = -EINVAL;
         goto out;
     }
 
-    vs->fidp->fs.dir = v9fs_do_opendir(s, &vs->fullname);
-    v9fs_create_post_opendir(s, vs, err);
-    return;
-
-out:
-    v9fs_post_create(s, vs, err);
-}
-
-static void v9fs_create_post_mkdir(V9fsState *s, V9fsCreateState *vs, int err)
-{
-    if (err < 0) {
+    v9fs_string_sprintf(&fullname, "%s/%s", fidp->path.data, name.data);
+    err = v9fs_co_lstat(pdu->s, &fullname, &stbuf);
+    if (!err) {
+        err = -EEXIST;
+        goto out;
+    } else if (err != -ENOENT) {
         goto out;
     }
-
-    err = v9fs_do_lstat(s, &vs->fullname, &vs->stbuf);
-    v9fs_create_post_dir_lstat(s, vs, err);
-    return;
-
-out:
-    v9fs_post_create(s, vs, err);
-}
-
-static void v9fs_create_post_fstat(V9fsState *s, V9fsCreateState *vs, int err)
-{
-    if (err) {
-        vs->fidp->fid_type = P9_FID_NONE;
-        close(vs->fidp->fs.fd);
-        err = -errno;
-    }
-    v9fs_post_create(s, vs, err);
-    return;
-}
-
-static void v9fs_create_post_open2(V9fsState *s, V9fsCreateState *vs, int err)
-{
-    if (vs->fidp->fs.fd == -1) {
-        err = -errno;
-        goto out;
-    }
-    vs->fidp->fid_type = P9_FID_FILE;
-    err = v9fs_do_fstat(s, vs->fidp->fs.fd, &vs->stbuf);
-    v9fs_create_post_fstat(s, vs, err);
-
-    return;
-
-out:
-    v9fs_post_create(s, vs, err);
-
-}
-
-static void v9fs_create_post_lstat(V9fsState *s, V9fsCreateState *vs, int err)
-{
-
-    if (err == 0 || errno != ENOENT) {
-        err = -errno;
-        goto out;
-    }
-
-    if (vs->perm & P9_STAT_MODE_DIR) {
-        err = v9fs_co_mkdir(s, vs->fullname.data, vs->perm & 0777,
-                vs->fidp->uid, -1);
-        v9fs_create_post_mkdir(s, vs, err);
-    } else if (vs->perm & P9_STAT_MODE_SYMLINK) {
-        err = v9fs_do_symlink(s, vs->fidp, vs->extension.data,
-                vs->fullname.data, -1);
-        v9fs_create_post_perms(s, vs, err);
-    } else if (vs->perm & P9_STAT_MODE_LINK) {
-        int32_t nfid = atoi(vs->extension.data);
-        V9fsFidState *nfidp = lookup_fid(s, nfid);
+    if (perm & P9_STAT_MODE_DIR) {
+        err = v9fs_co_mkdir(pdu->s, fullname.data, perm & 0777,
+                            fidp->uid, -1);
+        if (err < 0) {
+            goto out;
+        }
+        err = v9fs_co_opendir(pdu->s, fidp);
+        if (err < 0) {
+            goto out;
+        }
+        fidp->fid_type = P9_FID_DIR;
+    } else if (perm & P9_STAT_MODE_SYMLINK) {
+        err = v9fs_co_symlink(pdu->s, fidp, extension.data,
+                              fullname.data, -1);
+        if (err < 0) {
+            goto out;
+        }
+    } else if (perm & P9_STAT_MODE_LINK) {
+        int32_t nfid = atoi(extension.data);
+        V9fsFidState *nfidp = lookup_fid(pdu->s, nfid);
         if (nfidp == NULL) {
-            err = -errno;
-            v9fs_post_create(s, vs, err);
+            err = -EINVAL;
+            goto out;
         }
-        err = v9fs_do_link(s, &nfidp->path, &vs->fullname);
-        v9fs_create_post_perms(s, vs, err);
-    } else if (vs->perm & P9_STAT_MODE_DEVICE) {
+        err = v9fs_co_link(pdu->s, &nfidp->path, &fullname);
+        if (err < 0) {
+            goto out;
+        }
+    } else if (perm & P9_STAT_MODE_DEVICE) {
         char ctype;
         uint32_t major, minor;
         mode_t nmode = 0;
 
-        if (sscanf(vs->extension.data, "%c %u %u", &ctype, &major,
-                                        &minor) != 3) {
+        if (sscanf(extension.data, "%c %u %u", &ctype, &major, &minor) != 3) {
             err = -errno;
-            v9fs_post_create(s, vs, err);
+            goto out;
         }
 
         switch (ctype) {
@@ -2390,134 +1907,95 @@
             break;
         default:
             err = -EIO;
-            v9fs_post_create(s, vs, err);
+            goto out;
         }
 
-        nmode |= vs->perm & 0777;
-        err = v9fs_do_mknod(s, vs->fullname.data, nmode,
-                makedev(major, minor), vs->fidp->uid, -1);
-        v9fs_create_post_perms(s, vs, err);
-    } else if (vs->perm & P9_STAT_MODE_NAMED_PIPE) {
-        err = v9fs_do_mknod(s, vs->fullname.data, S_IFIFO | (vs->perm & 0777),
-                0, vs->fidp->uid, -1);
-        v9fs_post_create(s, vs, err);
-    } else if (vs->perm & P9_STAT_MODE_SOCKET) {
-        err = v9fs_do_mknod(s, vs->fullname.data, S_IFSOCK | (vs->perm & 0777),
-                0, vs->fidp->uid, -1);
-        v9fs_post_create(s, vs, err);
+        nmode |= perm & 0777;
+        err = v9fs_co_mknod(pdu->s, &fullname, fidp->uid, -1,
+                            makedev(major, minor), nmode);
+        if (err < 0) {
+            goto out;
+        }
+    } else if (perm & P9_STAT_MODE_NAMED_PIPE) {
+        err = v9fs_co_mknod(pdu->s, &fullname, fidp->uid, -1,
+                            0, S_IFIFO | (perm & 0777));
+        if (err < 0) {
+            goto out;
+        }
+    } else if (perm & P9_STAT_MODE_SOCKET) {
+        err = v9fs_co_mknod(pdu->s, &fullname, fidp->uid, -1,
+                            0, S_IFSOCK | (perm & 0777));
+        if (err < 0) {
+            goto out;
+        }
     } else {
-        vs->fidp->fs.fd = v9fs_do_open2(s, vs->fullname.data, vs->fidp->uid,
-                -1, omode_to_uflags(vs->mode)|O_CREAT, vs->perm);
-
-        v9fs_create_post_open2(s, vs, err);
+        err = v9fs_co_open2(pdu->s, fidp, fullname.data, -1,
+                            omode_to_uflags(mode)|O_CREAT, perm);
+        if (err < 0) {
+            goto out;
+        }
+        fidp->fid_type = P9_FID_FILE;
     }
-
-    return;
-
-out:
-    v9fs_post_create(s, vs, err);
-}
-
-static void v9fs_create(void *opaque)
-{
-    V9fsPDU *pdu = opaque;
-    V9fsState *s = pdu->s;
-    int32_t fid;
-    V9fsCreateState *vs;
-    int err = 0;
-
-    vs = g_malloc(sizeof(*vs));
-    vs->pdu = pdu;
-    vs->offset = 7;
-
-    v9fs_string_init(&vs->fullname);
-
-    pdu_unmarshal(vs->pdu, vs->offset, "dsdbs", &fid, &vs->name,
-                                &vs->perm, &vs->mode, &vs->extension);
-
-    vs->fidp = lookup_fid(s, fid);
-    if (vs->fidp == NULL) {
-        err = -EINVAL;
+    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);
+        }
         goto out;
     }
-
-    v9fs_string_sprintf(&vs->fullname, "%s/%s", vs->fidp->path.data,
-                                                        vs->name.data);
-
-    err = v9fs_do_lstat(s, &vs->fullname, &vs->stbuf);
-    v9fs_create_post_lstat(s, vs, err);
-    return;
-
+    iounit = get_iounit(pdu->s, &fidp->path);
+    v9fs_string_copy(&fidp->path, &fullname);
+    stat_to_qid(&stbuf, &qid);
+    offset += pdu_marshal(pdu, offset, "Qd", &qid, iounit);
+    err = offset;
 out:
-    complete_pdu(s, vs->pdu, err);
-    v9fs_string_free(&vs->name);
-    v9fs_string_free(&vs->extension);
-    g_free(vs);
-}
-
-static void v9fs_post_symlink(V9fsState *s, V9fsSymlinkState *vs, int err)
-{
-    if (err == 0) {
-        stat_to_qid(&vs->stbuf, &vs->qid);
-        vs->offset += pdu_marshal(vs->pdu, vs->offset, "Q", &vs->qid);
-        err = vs->offset;
-    } else {
-        err = -errno;
-    }
-    complete_pdu(s, vs->pdu, err);
-    v9fs_string_free(&vs->name);
-    v9fs_string_free(&vs->symname);
-    v9fs_string_free(&vs->fullname);
-    g_free(vs);
-}
-
-static void v9fs_symlink_post_do_symlink(V9fsState *s, V9fsSymlinkState *vs,
-        int err)
-{
-    if (err) {
-        goto out;
-    }
-    err = v9fs_do_lstat(s, &vs->fullname, &vs->stbuf);
-out:
-    v9fs_post_symlink(s, vs, err);
+   complete_pdu(pdu->s, pdu, err);
+   v9fs_string_free(&name);
+   v9fs_string_free(&extension);
+   v9fs_string_free(&fullname);
 }
 
 static void v9fs_symlink(void *opaque)
 {
     V9fsPDU *pdu = opaque;
-    V9fsState *s = pdu->s;
+    V9fsString name;
+    V9fsString symname;
+    V9fsString fullname;
+    V9fsFidState *dfidp;
+    V9fsQID qid;
+    struct stat stbuf;
     int32_t dfid;
-    V9fsSymlinkState *vs;
     int err = 0;
     gid_t gid;
+    size_t offset = 7;
 
-    vs = g_malloc(sizeof(*vs));
-    vs->pdu = pdu;
-    vs->offset = 7;
+    v9fs_string_init(&fullname);
+    pdu_unmarshal(pdu, offset, "dssd", &dfid, &name, &symname, &gid);
 
-    v9fs_string_init(&vs->fullname);
-
-    pdu_unmarshal(vs->pdu, vs->offset, "dssd", &dfid, &vs->name,
-            &vs->symname, &gid);
-
-    vs->dfidp = lookup_fid(s, dfid);
-    if (vs->dfidp == NULL) {
+    dfidp = lookup_fid(pdu->s, dfid);
+    if (dfidp == NULL) {
         err = -EINVAL;
         goto out;
     }
 
-    v9fs_string_sprintf(&vs->fullname, "%s/%s", vs->dfidp->path.data,
-            vs->name.data);
-    err = v9fs_do_symlink(s, vs->dfidp, vs->symname.data,
-            vs->fullname.data, gid);
-    v9fs_symlink_post_do_symlink(s, vs, err);
-    return;
-
+    v9fs_string_sprintf(&fullname, "%s/%s", dfidp->path.data, name.data);
+    err = v9fs_co_symlink(pdu->s, dfidp, symname.data, fullname.data, gid);
+    if (err < 0) {
+        goto out;
+    }
+    err = v9fs_co_lstat(pdu->s, &fullname, &stbuf);
+    if (err < 0) {
+        goto out;
+    }
+    stat_to_qid(&stbuf, &qid);
+    offset += pdu_marshal(pdu, offset, "Q", &qid);
+    err = offset;
 out:
-    complete_pdu(s, vs->pdu, err);
-    v9fs_string_free(&vs->name);
-    v9fs_string_free(&vs->symname);
-    g_free(vs);
+    complete_pdu(pdu->s, pdu, err);
+    v9fs_string_free(&name);
+    v9fs_string_free(&symname);
+    v9fs_string_free(&fullname);
 }
 
 static void v9fs_flush(void *opaque)
@@ -2545,21 +2023,20 @@
 
     dfidp = lookup_fid(s, dfid);
     if (dfidp == NULL) {
-        err = -errno;
+        err = -ENOENT;
         goto out;
     }
 
     oldfidp = lookup_fid(s, oldfid);
     if (oldfidp == NULL) {
-        err = -errno;
+        err = -ENOENT;
         goto out;
     }
 
     v9fs_string_sprintf(&fullname, "%s/%s", dfidp->path.data, name.data);
-    err = offset;
-    err = v9fs_do_link(s, &oldfidp->path, &fullname);
-    if (err) {
-        err = -errno;
+    err = v9fs_co_link(s, &oldfidp->path, &fullname);
+    if (!err) {
+        err = offset;
     }
     v9fs_string_free(&fullname);
 
@@ -2594,39 +2071,6 @@
     complete_pdu(pdu->s, pdu, err);
 }
 
-static void v9fs_wstat_post_truncate(V9fsState *s, V9fsWstatState *vs, int err)
-{
-    if (err < 0) {
-        goto out;
-    }
-
-    err = vs->offset;
-
-out:
-    v9fs_stat_free(&vs->v9stat);
-    complete_pdu(s, vs->pdu, err);
-    g_free(vs);
-}
-
-static void v9fs_wstat_post_rename(V9fsState *s, V9fsWstatState *vs, int err)
-{
-    if (err < 0) {
-        goto out;
-    }
-    if (vs->v9stat.length != -1) {
-        if (v9fs_do_truncate(s, &vs->fidp->path, vs->v9stat.length) < 0) {
-            err = -errno;
-        }
-    }
-    v9fs_wstat_post_truncate(s, vs, err);
-    return;
-
-out:
-    v9fs_stat_free(&vs->v9stat);
-    complete_pdu(s, vs->pdu, err);
-    g_free(vs);
-}
-
 static int v9fs_complete_rename(V9fsState *s, V9fsFidState *fidp,
                                 int32_t newdirfid, V9fsString *name)
 {
@@ -2695,24 +2139,6 @@
     return err;
 }
 
-static void v9fs_wstat_post_chown(V9fsState *s, V9fsWstatState *vs, int err)
-{
-    if (err < 0) {
-        goto out;
-    }
-
-    if (vs->v9stat.name.size != 0) {
-        err = v9fs_complete_rename(s, vs->fidp, -1, &vs->v9stat.name);
-    }
-    v9fs_wstat_post_rename(s, vs, err);
-    return;
-
-out:
-    v9fs_stat_free(&vs->v9stat);
-    complete_pdu(s, vs->pdu, err);
-    g_free(vs);
-}
-
 static void v9fs_rename(void *opaque)
 {
     int32_t fid;
@@ -2742,143 +2168,90 @@
     v9fs_string_free(&name);
 }
 
-static void v9fs_wstat_post_utime(V9fsState *s, V9fsWstatState *vs, int err)
+static void v9fs_wstat(void *opaque)
 {
-    if (err < 0) {
+    int32_t fid;
+    int err = 0;
+    int16_t unused;
+    V9fsStat v9stat;
+    size_t offset = 7;
+    struct stat stbuf;
+    V9fsFidState *fidp;
+    V9fsPDU *pdu = opaque;
+    V9fsState *s = pdu->s;
+
+    pdu_unmarshal(pdu, offset, "dwS", &fid, &unused, &v9stat);
+    fidp = lookup_fid(s, fid);
+    if (fidp == NULL) {
+        err = -EINVAL;
         goto out;
     }
-
-    if (vs->v9stat.n_gid != -1 || vs->v9stat.n_uid != -1) {
-        if (v9fs_do_chown(s, &vs->fidp->path, vs->v9stat.n_uid,
-                    vs->v9stat.n_gid)) {
-            err = -errno;
+    /* do we need to sync the file? */
+    if (donttouch_stat(&v9stat)) {
+        err = v9fs_co_fsync(s, fidp, 0);
+        goto out;
+    }
+    if (v9stat.mode != -1) {
+        uint32_t v9_mode;
+        err = v9fs_co_lstat(s, &fidp->path, &stbuf);
+        if (err < 0) {
+            goto out;
+        }
+        v9_mode = stat_to_v9mode(&stbuf);
+        if ((v9stat.mode & P9_STAT_MODE_TYPE_BITS) !=
+            (v9_mode & P9_STAT_MODE_TYPE_BITS)) {
+            /* Attempting to change the type */
+            err = -EIO;
+            goto out;
+        }
+        err = v9fs_co_chmod(s, &fidp->path,
+                            v9mode_to_mode(v9stat.mode,
+                                           &v9stat.extension));
+        if (err < 0) {
+            goto out;
         }
     }
-    v9fs_wstat_post_chown(s, vs, err);
-    return;
-
-out:
-    v9fs_stat_free(&vs->v9stat);
-    complete_pdu(s, vs->pdu, err);
-    g_free(vs);
-}
-
-static void v9fs_wstat_post_chmod(V9fsState *s, V9fsWstatState *vs, int err)
-{
-    if (err < 0) {
-        goto out;
-    }
-
-    if (vs->v9stat.mtime != -1 || vs->v9stat.atime != -1) {
+    if (v9stat.mtime != -1 || v9stat.atime != -1) {
         struct timespec times[2];
-        if (vs->v9stat.atime != -1) {
-            times[0].tv_sec = vs->v9stat.atime;
+        if (v9stat.atime != -1) {
+            times[0].tv_sec = v9stat.atime;
             times[0].tv_nsec = 0;
         } else {
             times[0].tv_nsec = UTIME_OMIT;
         }
-        if (vs->v9stat.mtime != -1) {
-            times[1].tv_sec = vs->v9stat.mtime;
+        if (v9stat.mtime != -1) {
+            times[1].tv_sec = v9stat.mtime;
             times[1].tv_nsec = 0;
         } else {
             times[1].tv_nsec = UTIME_OMIT;
         }
-
-        if (v9fs_do_utimensat(s, &vs->fidp->path, times)) {
-            err = -errno;
+        err = v9fs_co_utimensat(s, &fidp->path, times);
+        if (err < 0) {
+            goto out;
         }
     }
-
-    v9fs_wstat_post_utime(s, vs, err);
-    return;
-
-out:
-    v9fs_stat_free(&vs->v9stat);
-    complete_pdu(s, vs->pdu, err);
-    g_free(vs);
-}
-
-static void v9fs_wstat_post_fsync(V9fsState *s, V9fsWstatState *vs, int err)
-{
-    if (err == -1) {
-        err = -errno;
-    }
-    v9fs_stat_free(&vs->v9stat);
-    complete_pdu(s, vs->pdu, err);
-    g_free(vs);
-}
-
-static void v9fs_wstat_post_lstat(V9fsState *s, V9fsWstatState *vs, int err)
-{
-    uint32_t v9_mode;
-
-    if (err == -1) {
-        err = -errno;
-        goto out;
-    }
-
-    v9_mode = stat_to_v9mode(&vs->stbuf);
-
-    if ((vs->v9stat.mode & P9_STAT_MODE_TYPE_BITS) !=
-        (v9_mode & P9_STAT_MODE_TYPE_BITS)) {
-            /* Attempting to change the type */
-            err = -EIO;
+    if (v9stat.n_gid != -1 || v9stat.n_uid != -1) {
+        err = v9fs_co_chown(s, &fidp->path, v9stat.n_uid, v9stat.n_gid);
+        if (err < 0) {
             goto out;
+        }
     }
-
-    if (v9fs_do_chmod(s, &vs->fidp->path, v9mode_to_mode(vs->v9stat.mode,
-                    &vs->v9stat.extension))) {
-            err = -errno;
-     }
-    v9fs_wstat_post_chmod(s, vs, err);
-    return;
-
+    if (v9stat.name.size != 0) {
+        err = v9fs_complete_rename(s, fidp, -1, &v9stat.name);
+        if (err < 0) {
+            goto out;
+        }
+    }
+    if (v9stat.length != -1) {
+        err = v9fs_co_truncate(s, &fidp->path, v9stat.length);
+        if (err < 0) {
+            goto out;
+        }
+    }
+    err = offset;
 out:
-    v9fs_stat_free(&vs->v9stat);
-    complete_pdu(s, vs->pdu, err);
-    g_free(vs);
-}
-
-static void v9fs_wstat(void *opaque)
-{
-    V9fsPDU *pdu = opaque;
-    V9fsState *s = pdu->s;
-    int32_t fid;
-    V9fsWstatState *vs;
-    int err = 0;
-
-    vs = g_malloc(sizeof(*vs));
-    vs->pdu = pdu;
-    vs->offset = 7;
-
-    pdu_unmarshal(pdu, vs->offset, "dwS", &fid, &vs->unused, &vs->v9stat);
-
-    vs->fidp = lookup_fid(s, fid);
-    if (vs->fidp == NULL) {
-        err = -EINVAL;
-        goto out;
-    }
-
-    /* do we need to sync the file? */
-    if (donttouch_stat(&vs->v9stat)) {
-        err = v9fs_do_fsync(s, vs->fidp->fs.fd, 0);
-        v9fs_wstat_post_fsync(s, vs, err);
-        return;
-    }
-
-    if (vs->v9stat.mode != -1) {
-        err = v9fs_do_lstat(s, &vs->fidp->path, &vs->stbuf);
-        v9fs_wstat_post_lstat(s, vs, err);
-        return;
-    }
-
-    v9fs_wstat_post_chmod(s, vs, err);
-    return;
-
-out:
-    v9fs_stat_free(&vs->v9stat);
-    complete_pdu(s, vs->pdu, err);
-    g_free(vs);
+    v9fs_stat_free(&v9stat);
+    complete_pdu(s, pdu, err);
 }
 
 static int v9fs_fill_statfs(V9fsState *s, V9fsPDU *pdu, struct statfs *stbuf)
@@ -3006,89 +2379,81 @@
  * do any thing in * qemu 9p server side lock code path.
  * So when a TLOCK request comes, always return success
  */
-
 static void v9fs_lock(void *opaque)
 {
+    int8_t status;
+    V9fsFlock *flock;
+    size_t offset = 7;
+    struct stat stbuf;
+    V9fsFidState *fidp;
+    int32_t fid, err = 0;
     V9fsPDU *pdu = opaque;
     V9fsState *s = pdu->s;
-    int32_t fid, err = 0;
-    V9fsLockState *vs;
 
-    vs = g_malloc0(sizeof(*vs));
-    vs->pdu = pdu;
-    vs->offset = 7;
-
-    vs->flock = g_malloc(sizeof(*vs->flock));
-    pdu_unmarshal(vs->pdu, vs->offset, "dbdqqds", &fid, &vs->flock->type,
-                &vs->flock->flags, &vs->flock->start, &vs->flock->length,
-                            &vs->flock->proc_id, &vs->flock->client_id);
-
-    vs->status = P9_LOCK_ERROR;
+    flock = g_malloc(sizeof(*flock));
+    pdu_unmarshal(pdu, offset, "dbdqqds", &fid, &flock->type,
+                  &flock->flags, &flock->start, &flock->length,
+                  &flock->proc_id, &flock->client_id);
+    status = P9_LOCK_ERROR;
 
     /* We support only block flag now (that too ignored currently) */
-    if (vs->flock->flags & ~P9_LOCK_FLAGS_BLOCK) {
+    if (flock->flags & ~P9_LOCK_FLAGS_BLOCK) {
         err = -EINVAL;
         goto out;
     }
-    vs->fidp = lookup_fid(s, fid);
-    if (vs->fidp == NULL) {
+    fidp = lookup_fid(s, fid);
+    if (fidp == NULL) {
         err = -ENOENT;
         goto out;
     }
-
-    err = v9fs_do_fstat(s, vs->fidp->fs.fd, &vs->stbuf);
+    err = v9fs_co_fstat(s, fidp->fs.fd, &stbuf);
     if (err < 0) {
-        err = -errno;
         goto out;
     }
-    vs->status = P9_LOCK_SUCCESS;
+    status = P9_LOCK_SUCCESS;
 out:
-    vs->offset += pdu_marshal(vs->pdu, vs->offset, "b", vs->status);
-    complete_pdu(s, vs->pdu, err);
-    g_free(vs->flock);
-    g_free(vs);
+    err = offset;
+    err += pdu_marshal(pdu, offset, "b", status);
+    complete_pdu(s, pdu, err);
+    g_free(flock);
 }
 
 /*
  * When a TGETLOCK request comes, always return success because all lock
  * handling is done by client's VFS layer.
  */
-
 static void v9fs_getlock(void *opaque)
 {
+    size_t offset = 7;
+    struct stat stbuf;
+    V9fsFidState *fidp;
+    V9fsGetlock *glock;
+    int32_t fid, err = 0;
     V9fsPDU *pdu = opaque;
     V9fsState *s = pdu->s;
-    int32_t fid, err = 0;
-    V9fsGetlockState *vs;
 
-    vs = g_malloc0(sizeof(*vs));
-    vs->pdu = pdu;
-    vs->offset = 7;
+    glock = g_malloc(sizeof(*glock));
+    pdu_unmarshal(pdu, offset, "dbqqds", &fid, &glock->type,
+                  &glock->start, &glock->length, &glock->proc_id,
+                  &glock->client_id);
 
-    vs->glock = g_malloc(sizeof(*vs->glock));
-    pdu_unmarshal(vs->pdu, vs->offset, "dbqqds", &fid, &vs->glock->type,
-                &vs->glock->start, &vs->glock->length, &vs->glock->proc_id,
-		&vs->glock->client_id);
-
-    vs->fidp = lookup_fid(s, fid);
-    if (vs->fidp == NULL) {
+    fidp = lookup_fid(s, fid);
+    if (fidp == NULL) {
         err = -ENOENT;
         goto out;
     }
-
-    err = v9fs_do_fstat(s, vs->fidp->fs.fd, &vs->stbuf);
+    err = v9fs_co_fstat(s, fidp->fs.fd, &stbuf);
     if (err < 0) {
-        err = -errno;
         goto out;
     }
-    vs->glock->type = F_UNLCK;
-    vs->offset += pdu_marshal(vs->pdu, vs->offset, "bqqds", vs->glock->type,
-                vs->glock->start, vs->glock->length, vs->glock->proc_id,
-		&vs->glock->client_id);
+    glock->type = F_UNLCK;
+    offset += pdu_marshal(pdu, offset, "bqqds", glock->type,
+                          glock->start, glock->length, glock->proc_id,
+                          &glock->client_id);
+    err = offset;
 out:
-    complete_pdu(s, vs->pdu, err);
-    g_free(vs->glock);
-    g_free(vs);
+    complete_pdu(s, pdu, err);
+    g_free(glock);
 }
 
 static void v9fs_mkdir(void *opaque)
diff --git a/hw/9pfs/virtio-9p.h b/hw/9pfs/virtio-9p.h
index 46d79da..1d8c1b1 100644
--- a/hw/9pfs/virtio-9p.h
+++ b/hw/9pfs/virtio-9p.h
@@ -222,31 +222,6 @@
     int32_t msize;
 } V9fsState;
 
-typedef struct V9fsCreateState {
-    V9fsPDU *pdu;
-    size_t offset;
-    V9fsFidState *fidp;
-    V9fsQID qid;
-    int32_t perm;
-    int8_t mode;
-    struct stat stbuf;
-    V9fsString name;
-    V9fsString extension;
-    V9fsString fullname;
-    int iounit;
-} V9fsCreateState;
-
-typedef struct V9fsLcreateState {
-    V9fsPDU *pdu;
-    size_t offset;
-    V9fsFidState *fidp;
-    V9fsQID qid;
-    int32_t iounit;
-    struct stat stbuf;
-    V9fsString name;
-    V9fsString fullname;
-} V9fsLcreateState;
-
 typedef struct V9fsStatState {
     V9fsPDU *pdu;
     size_t offset;
@@ -278,19 +253,6 @@
     uint64_t st_data_version;
 } V9fsStatDotl;
 
-typedef struct V9fsWalkState {
-    V9fsPDU *pdu;
-    size_t offset;
-    uint16_t nwnames;
-    int name_idx;
-    V9fsQID *qids;
-    V9fsFidState *fidp;
-    V9fsFidState *newfidp;
-    V9fsString path;
-    V9fsString *wnames;
-    struct stat stbuf;
-} V9fsWalkState;
-
 typedef struct V9fsOpenState {
     V9fsPDU *pdu;
     size_t offset;
@@ -333,28 +295,6 @@
     int cnt;
 } V9fsWriteState;
 
-typedef struct V9fsWstatState
-{
-    V9fsPDU *pdu;
-    size_t offset;
-    int16_t unused;
-    V9fsStat v9stat;
-    V9fsFidState *fidp;
-    struct stat stbuf;
-} V9fsWstatState;
-
-typedef struct V9fsSymlinkState
-{
-    V9fsPDU *pdu;
-    size_t offset;
-    V9fsString name;
-    V9fsString symname;
-    V9fsString fullname;
-    V9fsFidState *dfidp;
-    V9fsQID qid;
-    struct stat stbuf;
-} V9fsSymlinkState;
-
 typedef struct V9fsIattr
 {
     int32_t valid;
@@ -403,16 +343,6 @@
     V9fsString client_id;
 } V9fsFlock;
 
-typedef struct V9fsLockState
-{
-    V9fsPDU *pdu;
-    size_t offset;
-    int8_t status;
-    struct stat stbuf;
-    V9fsFidState *fidp;
-    V9fsFlock *flock;
-} V9fsLockState;
-
 typedef struct V9fsGetlock
 {
     uint8_t type;
@@ -422,15 +352,6 @@
     V9fsString client_id;
 } V9fsGetlock;
 
-typedef struct V9fsGetlockState
-{
-    V9fsPDU *pdu;
-    size_t offset;
-    struct stat stbuf;
-    V9fsFidState *fidp;
-    V9fsGetlock *glock;
-} V9fsGetlockState;
-
 size_t pdu_packunpack(void *addr, struct iovec *sg, int sg_count,
                       size_t offset, size_t size, int pack);
 
diff --git a/hw/an5206.c b/hw/an5206.c
index 04ca420..481ae60 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 @@
     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 @@
     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 f8a7472..af403a1 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 a932f16..28d41b8 100644
--- a/hw/armv7m.c
+++ b/hw/armv7m.c
@@ -156,7 +156,8 @@
    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 @@
     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 @@
 #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 @@
     /* 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 06200e2..73eb39d 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 @@
     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 @@
     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 4d0ef0d..ec7ea82 100644
--- a/hw/cirrus_vga.c
+++ b/hw/cirrus_vga.c
@@ -2424,6 +2424,7 @@
 {
     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 @@
             unmap_linear_vram(s);
         }
     }
+    memory_region_transaction_commit();
 }
 
 
diff --git a/hw/collie.c b/hw/collie.c
index 156404d..0b955e0 100644
--- a/hw/collie.c
+++ b/hw/collie.c
@@ -26,7 +26,7 @@
 {
     StrongARMState *s;
     DriveInfo *dinfo;
-    ram_addr_t phys_flash;
+    MemoryRegion *phys_flash = g_new(MemoryRegion, 2);
 
     if (!cpu_model) {
         cpu_model = "sa1110";
@@ -34,17 +34,19 @@
 
     s = sa1110_init(collie_binfo.ram_size, cpu_model);
 
-    phys_flash = qemu_ram_alloc(NULL, "collie.fl1", 0x02000000);
+    memory_region_init_rom_device(&phys_flash[0], &pflash_cfi01_ops_le,
+                                  NULL, "collie.fl1", 0x02000000);
     dinfo = drive_get(IF_PFLASH, 0, 0);
-    pflash_cfi01_register(SA_CS0, phys_flash,
+    pflash_cfi01_register(SA_CS0, &phys_flash[0],
                     dinfo ? dinfo->bdrv : NULL, (64 * 1024),
-                    512, 4, 0x00, 0x00, 0x00, 0x00, 0);
+                    512, 4, 0x00, 0x00, 0x00, 0x00);
 
-    phys_flash = qemu_ram_alloc(NULL, "collie.fl2", 0x02000000);
+    memory_region_init_rom_device(&phys_flash[1], &pflash_cfi01_ops_le,
+                                  NULL, "collie.fl2", 0x02000000);
     dinfo = drive_get(IF_PFLASH, 0, 1);
-    pflash_cfi01_register(SA_CS1, phys_flash,
+    pflash_cfi01_register(SA_CS1, &phys_flash[1],
                     dinfo ? dinfo->bdrv : NULL, (64 * 1024),
-                    512, 4, 0x00, 0x00, 0x00, 0x00, 0);
+                    512, 4, 0x00, 0x00, 0x00, 0x00);
 
     sysbus_create_simple("scoop", 0x40800000, NULL);
 
diff --git a/hw/dec_pci.c b/hw/dec_pci.c
index a35f382..1aec066 100644
--- a/hw/dec_pci.c
+++ b/hw/dec_pci.c
@@ -80,16 +80,15 @@
 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 eed9e38..30146b9 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 @@
                      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 @@
     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/flash.h b/hw/flash.h
index 140ae39..7fb012b 100644
--- a/hw/flash.h
+++ b/hw/flash.h
@@ -1,21 +1,27 @@
+#include "memory.h"
+
 /* NOR flash devices */
 typedef struct pflash_t pflash_t;
 
 /* pflash_cfi01.c */
-pflash_t *pflash_cfi01_register(target_phys_addr_t base, ram_addr_t off,
+extern const MemoryRegionOps pflash_cfi01_ops_be;
+extern const MemoryRegionOps pflash_cfi01_ops_le;
+extern const MemoryRegionOps pflash_cfi02_ops_be;
+extern const MemoryRegionOps pflash_cfi02_ops_le;
+
+pflash_t *pflash_cfi01_register(target_phys_addr_t base, MemoryRegion *mem,
                                 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);
 
 /* 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, MemoryRegion *mem,
                                 BlockDriverState *bs, uint32_t sector_len,
                                 int nb_blocs, int nb_mappings, int width,
                                 uint16_t id0, uint16_t id1,
                                 uint16_t id2, uint16_t id3,
-                                uint16_t unlock_addr0, uint16_t unlock_addr1,
-                                int be);
+                                uint16_t unlock_addr0, uint16_t unlock_addr1);
 
 /* nand.c */
 DeviceState *nand_init(BlockDriverState *bdrv, int manf_id, int chip_id);
diff --git a/hw/g364fb.c b/hw/g364fb.c
index b3020c5..a7731ec 100644
--- a/hw/g364fb.c
+++ b/hw/g364fb.c
@@ -36,7 +36,7 @@
 typedef struct G364State {
     /* hardware */
     uint8_t *vram;
-    ram_addr_t vram_offset;
+    MemoryRegion vram_region;
     int vram_size;
     qemu_irq irq;
     /* registers */
@@ -68,16 +68,17 @@
 #define CTLA_FORCE_BLANK 0x00000400
 #define CTLA_NO_CURSOR   0x00800000
 
-static inline int check_dirty(ram_addr_t page)
+static inline int check_dirty(G364State *s, ram_addr_t page)
 {
-    return cpu_physical_memory_get_dirty(page, VGA_DIRTY_FLAG);
+    return memory_region_get_dirty(&s->vram_region, page, DIRTY_MEMORY_VGA);
 }
 
 static inline void reset_dirty(G364State *s,
                                ram_addr_t page_min, ram_addr_t page_max)
 {
-    cpu_physical_memory_reset_dirty(page_min, page_max + TARGET_PAGE_SIZE - 1,
-                                    VGA_DIRTY_FLAG);
+    memory_region_reset_dirty(&s->vram_region, page_min,
+                              page_max + TARGET_PAGE_SIZE - 1,
+                              DIRTY_MEMORY_VGA);
 }
 
 static void g364fb_draw_graphic8(G364State *s)
@@ -114,7 +115,7 @@
             return;
     }
 
-    page = s->vram_offset;
+    page = 0;
     page_min = (ram_addr_t)-1;
     page_max = 0;
 
@@ -135,7 +136,7 @@
     /* XXX: out of range in vram? */
     data_display = dd = ds_get_data(s->ds);
     while (y < s->height) {
-        if (check_dirty(page)) {
+        if (check_dirty(s, page)) {
             if (y < ymin)
                 ymin = ymax = y;
             if (page_min == (ram_addr_t)-1)
@@ -275,7 +276,7 @@
 
     s->blanked = 0;
     for (i = 0; i < s->vram_size; i += TARGET_PAGE_SIZE) {
-        cpu_physical_memory_set_dirty(s->vram_offset + i);
+        memory_region_set_dirty(&s->vram_region, i);
     }
 }
 
@@ -411,7 +412,7 @@
     end = (ymax + 1) * ds_get_linesize(s->ds);
 
     for (i = start; i < end; i += TARGET_PAGE_SIZE) {
-        cpu_physical_memory_set_dirty(s->vram_offset + i);
+        memory_region_set_dirty(&s->vram_region, i);
     }
 }
 
@@ -522,16 +523,20 @@
     g364fb_ctrl_writel(opaque, addr & ~0x3, val);
 }
 
-static CPUReadMemoryFunc * const g364fb_ctrl_read[3] = {
-    g364fb_ctrl_readb,
-    g364fb_ctrl_readw,
-    g364fb_ctrl_readl,
-};
-
-static CPUWriteMemoryFunc * const g364fb_ctrl_write[3] = {
-    g364fb_ctrl_writeb,
-    g364fb_ctrl_writew,
-    g364fb_ctrl_writel,
+static const MemoryRegionOps g364fb_ctrl_ops = {
+    .old_mmio = {
+        .read = {
+            g364fb_ctrl_readb,
+            g364fb_ctrl_readw,
+            g364fb_ctrl_readl,
+        },
+        .write = {
+            g364fb_ctrl_writeb,
+            g364fb_ctrl_writew,
+            g364fb_ctrl_writel,
+        },
+    },
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static int g364fb_load(QEMUFile *f, void *opaque, int version_id)
@@ -583,18 +588,19 @@
     qemu_put_be32(f, s->height);
 }
 
-int g364fb_mm_init(target_phys_addr_t vram_base,
+int g364fb_mm_init(MemoryRegion *system_memory,
+                   target_phys_addr_t vram_base,
                    target_phys_addr_t ctrl_base, int it_shift,
                    qemu_irq irq)
 {
     G364State *s;
-    int io_ctrl;
+    MemoryRegion *io_ctrl = g_new(MemoryRegion, 1);
 
     s = g_malloc0(sizeof(G364State));
 
     s->vram_size = 8 * 1024 * 1024;
-    s->vram_offset = qemu_ram_alloc(NULL, "g364fb.vram", s->vram_size);
-    s->vram = qemu_get_ram_ptr(s->vram_offset);
+    memory_region_init_ram(&s->vram_region, NULL, "g364fb.vram", s->vram_size);
+    s->vram = memory_region_get_ram_ptr(&s->vram_region);
     s->irq = irq;
 
     qemu_register_reset(g364fb_reset, s);
@@ -605,11 +611,11 @@
                                  g364fb_invalidate_display,
                                  g364fb_screen_dump, NULL, s);
 
-    cpu_register_physical_memory(vram_base, s->vram_size, s->vram_offset);
+    memory_region_add_subregion(system_memory, vram_base, &s->vram_region);
 
-    io_ctrl = cpu_register_io_memory(g364fb_ctrl_read, g364fb_ctrl_write, s,
-                                     DEVICE_NATIVE_ENDIAN);
-    cpu_register_physical_memory(ctrl_base, 0x200000, io_ctrl);
+    memory_region_init_io(io_ctrl, &g364fb_ctrl_ops, s,
+                          "g364fb-ctrl", 0x200000);
+    memory_region_add_subregion(system_memory, ctrl_base, io_ctrl);
 
     return 0;
 }
diff --git a/hw/grackle_pci.c b/hw/grackle_pci.c
index 9a823e1..9d3ff7d 100644
--- a/hw/grackle_pci.c
+++ b/hw/grackle_pci.c
@@ -92,16 +92,15 @@
 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 853f7e1..d3a4bb4 100644
--- a/hw/gumstix.c
+++ b/hw/gumstix.c
@@ -48,7 +48,8 @@
 {
     PXA2xxState *cpu;
     DriveInfo *dinfo;
-    int be;
+    const MemoryRegionOps *flash_ops;
+    MemoryRegion *flash = g_new(MemoryRegion, 1);
 
     uint32_t connex_rom = 0x01000000;
     uint32_t connex_ram = 0x04000000;
@@ -63,14 +64,15 @@
     }
 
 #ifdef TARGET_WORDS_BIGENDIAN
-    be = 1;
+    flash_ops = &pflash_cfi01_ops_be;
 #else
-    be = 0;
+    flash_ops = &pflash_cfi01_ops_le;
 #endif
-    if (!pflash_cfi01_register(0x00000000, qemu_ram_alloc(NULL, "connext.rom",
-                                                          connex_rom),
+    memory_region_init_rom_device(flash, flash_ops,
+                                  NULL, "connext.rom", connex_rom);
+    if (!pflash_cfi01_register(0x00000000, flash,
                                dinfo->bdrv, sector_len, connex_rom / sector_len,
-                               2, 0, 0, 0, 0, be)) {
+                               2, 0, 0, 0, 0)) {
         fprintf(stderr, "qemu: Error registering flash memory.\n");
         exit(1);
     }
@@ -87,7 +89,8 @@
 {
     PXA2xxState *cpu;
     DriveInfo *dinfo;
-    int be;
+    MemoryRegion *flash = g_new(MemoryRegion, 1);
+    const MemoryRegionOps *flash_ops;
 
     uint32_t verdex_rom = 0x02000000;
     uint32_t verdex_ram = 0x10000000;
@@ -102,14 +105,15 @@
     }
 
 #ifdef TARGET_WORDS_BIGENDIAN
-    be = 1;
+    flash_ops = &pflash_cfi01_ops_be;
 #else
-    be = 0;
+    flash_ops = &pflash_cfi01_ops_le;
 #endif
-    if (!pflash_cfi01_register(0x00000000, qemu_ram_alloc(NULL, "verdex.rom",
-                                                          verdex_rom),
+    memory_region_init_rom_device(flash, flash_ops,
+                                  NULL, "verdex.rom", verdex_rom);
+    if (!pflash_cfi01_register(0x00000000, flash,
                                dinfo->bdrv, sector_len, verdex_rom / sector_len,
-                               2, 0, 0, 0, 0, be)) {
+                               2, 0, 0, 0, 0)) {
         fprintf(stderr, "qemu: Error registering flash memory.\n");
         exit(1);
     }
diff --git a/hw/integratorcp.c b/hw/integratorcp.c
index 2814108..3c8982e 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 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 @@
     }
     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 @@
                      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 @@
         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 a62a941..607ec85 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 @@
                                   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 @@
         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 d18aad7..a84007b 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,9 @@
 {
     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);
+    MemoryRegion *phys_flash = g_new(MemoryRegion, 1);
     qemu_irq *cpu_irq, irq[32];
     ResetInfo *reset_info;
     int i;
@@ -105,16 +107,17 @@
 
     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);
+    memory_region_init_rom_device(phys_flash, &pflash_cfi02_ops_be,
+                                  NULL, "lm32_evr.flash", flash_size);
     dinfo = drive_get(IF_PFLASH, 0, 0);
     /* Spansion S29NS128P */
     pflash_cfi02_register(flash_base, phys_flash,
                           dinfo ? dinfo->bdrv : NULL, flash_sector_size,
                           flash_size / flash_sector_size, 1, 2,
-                          0x01, 0x7e, 0x43, 0x00, 0x555, 0x2aa, 1);
+                          0x01, 0x7e, 0x43, 0x00, 0x555, 0x2aa);
 
     /* create irq lines */
     cpu_irq = qemu_allocate_irqs(cpu_irq_handler, env, 1);
@@ -164,8 +167,9 @@
 {
     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);
+    MemoryRegion *phys_flash = g_new(MemoryRegion, 1);
     qemu_irq *cpu_irq, irq[32];
     HWSetup *hw;
     ResetInfo *reset_info;
@@ -200,16 +204,17 @@
 
     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);
+    memory_region_init_rom_device(phys_flash, &pflash_cfi01_ops_be,
+                                  NULL, "lm32_uclinux.flash", flash_size);
     dinfo = drive_get(IF_PFLASH, 0, 0);
     /* Spansion S29NS128P */
     pflash_cfi02_register(flash_base, phys_flash,
                           dinfo ? dinfo->bdrv : NULL, flash_sector_size,
                           flash_size / flash_sector_size, 1, 2,
-                          0x01, 0x7e, 0x43, 0x00, 0x555, 0x2aa, 1);
+                          0x01, 0x7e, 0x43, 0x00, 0x555, 0x2aa);
 
     /* create irq lines */
     cpu_irq = qemu_allocate_irqs(cpu_irq_handler, env, 1);
diff --git a/hw/mainstone.c b/hw/mainstone.c
index 4792f0e..82e9571 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 @@
     .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)
@@ -101,21 +103,23 @@
     DeviceState *mst_irq;
     DriveInfo *dinfo;
     int i;
-    int be;
+    MemoryRegion *rom = g_new(MemoryRegion, 1);
+    MemoryRegion *flashes = g_new(MemoryRegion, 2);
+    const MemoryRegionOps *flash_ops;
 
     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;
+    flash_ops = &pflash_cfi01_ops_be;
 #else
-    be = 0;
+    flash_ops = &pflash_cfi01_ops_le;
 #endif
     /* There are two 32MiB flash devices on the board */
     for (i = 0; i < 2; i ++) {
@@ -126,13 +130,14 @@
             exit(1);
         }
 
+        memory_region_init_rom_device(&flashes[i], flash_ops,
+                                      NULL, (i ? "mainstone.flash1"
+                                               : "mainstone.flash0"),
+                                      MAINSTONE_FLASH);
         if (!pflash_cfi01_register(mainstone_flash_base[i],
-                                   qemu_ram_alloc(NULL, i ? "mainstone.flash1" :
-                                                  "mainstone.flash0",
-                                                  MAINSTONE_FLASH),
-                                   dinfo->bdrv, sector_len,
-                                   MAINSTONE_FLASH / sector_len, 4, 0, 0, 0, 0,
-                                   be)) {
+                                   &flashes[i], dinfo->bdrv, sector_len,
+                                   MAINSTONE_FLASH / sector_len, 4, 0, 0, 0,
+                                   0)) {
             fprintf(stderr, "qemu: Error registering flash memory.\n");
             exit(1);
         }
@@ -170,7 +175,7 @@
                 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 8fe507f..1c2c0c4 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_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 @@
     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 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 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 const MemoryRegionOps m5208_sys_ops = {
+    .read = m5208_sys_read,
+    .write = m5208_sys_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
-static CPUWriteMemoryFunc * const m5208_sys_writefn[] = {
-   m5208_sys_write,
-   m5208_sys_write,
-   m5208_sys_write
-};
-
-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 @@
     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 @@
     /* 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 @@
     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 cd36026..fb48e37 100644
--- a/hw/milkymist-minimac2.c
+++ b/hw/milkymist-minimac2.c
@@ -97,6 +97,8 @@
     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 @@
     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 @@
 }
 
 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 @@
     }
 }
 
-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 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 fe4eedb..ef4d9ee 100644
--- a/hw/milkymist-softusb.c
+++ b/hw/milkymist-softusb.c
@@ -49,6 +49,9 @@
     HIDState hid_kbd;
     HIDState hid_mouse;
 
+    MemoryRegion regs_region;
+    MemoryRegion pmem;
+    MemoryRegion dmem;
     qemu_irq irq;
 
     /* device properties */
@@ -68,7 +71,8 @@
 };
 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 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 @@
     }
 }
 
-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 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 93288c8..ef21cca 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,9 @@
     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);
+    MemoryRegion *phys_flash = g_new(MemoryRegion, 1);
     qemu_irq irq[32], *cpu_irq;
     int i;
     char *bios_filename;
@@ -109,17 +111,17 @@
 
     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);
+    memory_region_init_rom_device(phys_flash, &pflash_cfi01_ops_be,
+                                  NULL, "milkymist.flash", flash_size);
     dinfo = drive_get(IF_PFLASH, 0, 0);
     /* Numonyx JS28F256J3F105 */
     pflash_cfi01_register(flash_base, phys_flash,
                           dinfo ? dinfo->bdrv : NULL, flash_sector_size,
                           flash_size / flash_sector_size, 2,
-                          0x00, 0x89, 0x00, 0x1d, 1);
+                          0x00, 0x89, 0x00, 0x1d);
 
     /* create irq lines */
     cpu_irq = qemu_allocate_irqs(cpu_irq_handler, env, 1);
diff --git a/hw/mips.h b/hw/mips.h
index cae5f4c..97d7b9e 100644
--- a/hw/mips.h
+++ b/hw/mips.h
@@ -2,6 +2,8 @@
 #define HW_MIPS_H
 /* Definitions for mips board emulation.  */
 
+#include "memory.h"
+
 /* gt64xxx.c */
 PCIBus *gt64120_register(qemu_irq *pic);
 
@@ -9,7 +11,7 @@
 PCIBus *bonito_init(qemu_irq *pic);
 
 /* g364fb.c */
-int g364fb_mm_init(target_phys_addr_t vram_base,
+int g364fb_mm_init(MemoryRegion *system_memory, target_phys_addr_t vram_base,
                    target_phys_addr_t ctrl_base, int it_shift,
                    qemu_irq irq);
 
diff --git a/hw/mips_jazz.c b/hw/mips_jazz.c
index 84ce061..a741086 100644
--- a/hw/mips_jazz.c
+++ b/hw/mips_jazz.c
@@ -195,7 +195,8 @@
     /* Video card */
     switch (jazz_model) {
     case JAZZ_MAGNUM:
-        g364fb_mm_init(0x40000000, 0x60000000, 0, rc4030[3]);
+        g364fb_mm_init(get_system_memory(), 0x40000000, 0x60000000, 0,
+                       rc4030[3]);
         break;
     case JAZZ_PICA61:
         isa_vga_mm_init(0x40000000, 0x60000000, 0, get_system_memory());
diff --git a/hw/mips_malta.c b/hw/mips_malta.c
index 86a8ba0..b5c9bcf 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
 
@@ -762,7 +763,10 @@
 {
     char *filename;
     ram_addr_t ram_offset;
-    ram_addr_t bios_offset;
+    MemoryRegion *address_space_mem = get_system_memory();
+    MemoryRegion *bios = g_new(MemoryRegion, 1);
+    MemoryRegion *bios_1e0 = g_new(MemoryRegion, 1);
+    MemoryRegion *bios_1fc = g_new(MemoryRegion, 1);
     target_long bios_size;
     int64_t kernel_entry;
     PCIBus *pci_bus;
@@ -777,7 +781,7 @@
     DriveInfo *fd[MAX_FD];
     int fl_idx = 0;
     int fl_sectors = 0;
-    int be;
+    const MemoryRegionOps *bios_ops;
 
     /* Make sure the first 3 serial ports are associated with a device. */
     for(i = 0; i < 3; i++) {
@@ -810,23 +814,24 @@
                 ((unsigned int)ram_size / (1 << 20)));
         exit(1);
     }
-    ram_offset = qemu_ram_alloc(NULL, "mips_malta.ram", ram_size);
-    bios_offset = qemu_ram_alloc(NULL, "mips_malta.bios", BIOS_SIZE);
+#ifdef TARGET_WORDS_BIGENDIAN
+    bios_ops = &pflash_cfi01_ops_be;
+#else
+    bios_ops = &pflash_cfi01_ops_le;
+#endif
 
+    ram_offset = qemu_ram_alloc(NULL, "mips_malta.ram", ram_size);
+    memory_region_init_rom_device(bios, bios_ops, 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);
+    memory_region_init_alias(bios_1e0, "bios-1e0", bios, 0, BIOS_SIZE);
+    memory_region_add_subregion(address_space_mem, 0x1e000000LL, bios_1e0);
+    memory_region_init_alias(bios_1fc, "bios-1fc", bios, 0, BIOS_SIZE);
+    memory_region_add_subregion(address_space_mem, 0x1fc00000LL, bios_1fc);
 
-#ifdef TARGET_WORDS_BIGENDIAN
-    be = 1;
-#else
-    be = 0;
-#endif
     /* FPGA */
     malta_fpga_init(0x1f000000LL, env->irq[2], serial_hds[2]);
 
@@ -838,7 +843,7 @@
         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) {
@@ -847,13 +852,13 @@
             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,
+            pflash_cfi01_register(0x1e000000LL, bios,
                                   dinfo->bdrv, 65536, fl_sectors,
-                                  4, 0x0000, 0x0000, 0x0000, 0x0000, be);
+                                  4, 0x0000, 0x0000, 0x0000, 0x0000);
             fl_idx++;
         } else {
             /* Load a BIOS image. */
@@ -878,7 +883,7 @@
            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);
@@ -890,7 +895,7 @@
     /* 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 9d90568..51dc868 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,8 @@
 {
     char *filename;
     ram_addr_t ram_offset;
-    ram_addr_t bios_offset;
+    MemoryRegion *address_space_mem = get_system_memory();
+    MemoryRegion *bios = g_new(MemoryRegion, 1);
     int bios_size;
     CPUState *env;
     ResetData *reset_info;
@@ -227,18 +229,20 @@
     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);
-
+        memory_region_init_ram(bios, NULL, "mips_r4k.bios", BIOS_SIZE);
+        memory_region_set_readonly(bios, true);
+        memory_region_add_subregion(address_space_mem, 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,
+        memory_region_init_rom_device(bios,
+                                      (be ? &pflash_cfi01_ops_be
+                                          : &pflash_cfi01_ops_le),
+                                      NULL, "mips_r4k.bios", mips_rom);
+        if (!pflash_cfi01_register(0x1fc00000, bios,
                                    dinfo->bdrv, sector_len,
                                    mips_rom / sector_len,
-                                   4, 0, 0, 0, 0, be)) {
+                                   4, 0, 0, 0, 0)) {
             fprintf(stderr, "qemu: Error registering flash memory.\n");
 	}
     }
diff --git a/hw/musicpal.c b/hw/musicpal.c
index 63dd391..5e74ee7 100644
--- a/hw/musicpal.c
+++ b/hw/musicpal.c
@@ -1502,6 +1502,7 @@
     unsigned long flash_size;
     DriveInfo *dinfo;
     ram_addr_t sram_off;
+    MemoryRegion *flash = g_new(MemoryRegion, 1);
 
     if (!cpu_model) {
         cpu_model = "arm926";
@@ -1565,21 +1566,23 @@
          * 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),
+        memory_region_init_rom_device(flash, &pflash_cfi02_ops_be,
+                                      NULL, "musicpal.flash", flash_size);
+        pflash_cfi02_register(0-MP_FLASH_SIZE_MAX, flash,
                               dinfo->bdrv, 0x10000,
                               (flash_size + 0xffff) >> 16,
                               MP_FLASH_SIZE_MAX / flash_size,
                               2, 0x00BF, 0x236D, 0x0000, 0x0000,
-                              0x5555, 0x2AAA, 1);
+                              0x5555, 0x2AAA);
 #else
-        pflash_cfi02_register(0-MP_FLASH_SIZE_MAX, qemu_ram_alloc(NULL,
-                              "musicpal.flash", flash_size),
+        memory_region_init_rom_device(flash, &pflash_cfi02_ops_le,
+                                      NULL, "musicpal.flash", flash_size);
+        pflash_cfi02_register(0-MP_FLASH_SIZE_MAX, flash,
                               dinfo->bdrv, 0x10000,
                               (flash_size + 0xffff) >> 16,
                               MP_FLASH_SIZE_MAX / flash_size,
                               2, 0x00BF, 0x236D, 0x0000, 0x0000,
-                              0x5555, 0x2AAA, 0);
+                              0x5555, 0x2AAA);
 #endif
 
     }
diff --git a/hw/omap_sx1.c b/hw/omap_sx1.c
index a7b687b..70364f4 100644
--- a/hw/omap_sx1.c
+++ b/hw/omap_sx1.c
@@ -129,7 +129,8 @@
     DriveInfo *dinfo;
     int fl_idx;
     uint32_t flash_size = flash0_size;
-    int be;
+    const MemoryRegionOps *flash_ops;
+    MemoryRegion *flash = g_new(MemoryRegion, 2);
 
     if (version == 2) {
         flash_size = flash2_size;
@@ -155,17 +156,18 @@
 
     fl_idx = 0;
 #ifdef TARGET_WORDS_BIGENDIAN
-    be = 1;
+    flash_ops = &pflash_cfi01_ops_be;
 #else
-    be = 0;
+    flash_ops = &pflash_cfi01_ops_le;
 #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),
+        memory_region_init_rom_device(&flash[0], flash_ops,
+                                      NULL, "omap_sx1.flash0-1", flash_size);
+        if (!pflash_cfi01_register(OMAP_CS0_BASE, &flash[0],
                                    dinfo->bdrv, sector_size,
                                    flash_size / sector_size,
-                                   4, 0, 0, 0, 0, be)) {
+                                   4, 0, 0, 0, 0)) {
             fprintf(stderr, "qemu: Error registering flash memory %d.\n",
                            fl_idx);
         }
@@ -182,11 +184,12 @@
         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),
+        memory_region_init_rom_device(&flash[1], flash_ops,
+                                      NULL, "omap_sx1.flash1-1", flash1_size);
+        if (!pflash_cfi01_register(OMAP_CS1_BASE, &flash[1],
                                    dinfo->bdrv, sector_size,
                                    flash1_size / sector_size,
-                                   4, 0, 0, 0, 0, be)) {
+                                   4, 0, 0, 0, 0)) {
             fprintf(stderr, "qemu: Error registering flash memory %d.\n",
                            fl_idx);
         }
diff --git a/hw/pci_host.c b/hw/pci_host.c
index 2e8a29f..44c6c20 100644
--- a/hw/pci_host.c
+++ b/hw/pci_host.c
@@ -94,82 +94,72 @@
     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,
+};
 
-int pci_host_data_register_mmio(PCIHostState *s, int endian)
-{
-    pci_host_init(s);
-    return cpu_register_io_memory_simple(&s->data_handler, endian);
-}
+const MemoryRegionOps pci_host_data_be_ops = {
+    .read = pci_host_data_read,
+    .write = pci_host_data_write,
+    .endianness = DEVICE_BIG_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 7f55114..0211086 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 @@
 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 e3ca310..257fcca 100644
--- a/hw/petalogix_ml605_mmu.c
+++ b/hw/petalogix_ml605_mmu.c
@@ -149,7 +149,7 @@
     target_phys_addr_t ddr_base = MEMORY_BASEADDR;
     ram_addr_t phys_lmb_bram;
     ram_addr_t phys_ram;
-    ram_addr_t phys_flash;
+    MemoryRegion *phys_flash = g_new(MemoryRegion, 1);
     qemu_irq irq[32], *cpu_irq;
 
     /* init CPUs */
@@ -169,14 +169,15 @@
     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);
+    memory_region_init_rom_device(phys_flash, &pflash_cfi01_ops_le,
+                                  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,
                           dinfo ? dinfo->bdrv : NULL, (64 * 1024),
                           FLASH_SIZE >> 16,
-                          2, 0x89, 0x18, 0x0000, 0x0, 0);
+                          2, 0x89, 0x18, 0x0000, 0x0);
 
 
     cpu_irq = microblaze_pic_init_cpu(env);
diff --git a/hw/petalogix_s3adsp1800_mmu.c b/hw/petalogix_s3adsp1800_mmu.c
index a43fb4c..1481745 100644
--- a/hw/petalogix_s3adsp1800_mmu.c
+++ b/hw/petalogix_s3adsp1800_mmu.c
@@ -127,7 +127,7 @@
     target_phys_addr_t ddr_base = 0x90000000;
     ram_addr_t phys_lmb_bram;
     ram_addr_t phys_ram;
-    ram_addr_t phys_flash;
+    MemoryRegion *phys_flash = g_new(MemoryRegion, 1);
     qemu_irq irq[32], *cpu_irq;
 
     /* init CPUs */
@@ -148,12 +148,14 @@
     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);
+    memory_region_init_rom_device(phys_flash, &pflash_cfi01_ops_be,
+                                  NULL, "petalogix_s3adsp1800.flash",
+                                  FLASH_SIZE);
     dinfo = drive_get(IF_PFLASH, 0, 0);
     pflash_cfi01_register(0xa0000000, phys_flash,
                           dinfo ? dinfo->bdrv : NULL, (64 * 1024),
                           FLASH_SIZE >> 16,
-                          1, 0x89, 0x18, 0x0000, 0x0, 1);
+                          1, 0x89, 0x18, 0x0000, 0x0);
 
     cpu_irq = microblaze_pic_init_cpu(env);
     dev = xilinx_intc_create(0x81800000, cpu_irq[0], 2);
diff --git a/hw/pflash_cfi01.c b/hw/pflash_cfi01.c
index 90e1301..2144c6a 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 @@
     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 @@
     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 @@
 
     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 @@
            __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 @@
     pflash_write(pfl, addr, value, 4, 0);
 }
 
-static CPUWriteMemoryFunc * const pflash_write_ops_be[] = {
-    &pflash_writeb_be,
-    &pflash_writew_be,
-    &pflash_writel_be,
+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,
+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,11 @@
     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, MemoryRegion *mem,
                                 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)
 {
     pflash_t *pfl;
     target_phys_addr_t total_len;
@@ -597,26 +586,16 @@
     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);
+    pfl->storage = memory_region_get_ram_ptr(mem);
+    pfl->mem = mem;
+    memory_region_add_subregion(get_system_memory(), base, 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(), mem);
             g_free(pfl);
             return NULL;
         }
diff --git a/hw/pflash_cfi02.c b/hw/pflash_cfi02.c
index ac5115e..e7e0408 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,39 @@
     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;
 };
 
+/*
+ * Set up replicated mappings of the same region.
+ */
+static void pflash_setup_mappings(pflash_t *pfl, MemoryRegion *mem)
+{
+    unsigned i;
+    target_phys_addr_t size = memory_region_size(mem);
+
+    pfl->orig_mem = 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", mem,
+                                 0, size);
+        memory_region_add_subregion(&pfl->mem, i * size, &pfl->mem_mappings[i]);
+    }
+}
+
 static void pflash_register_memory(pflash_t *pfl, int rom_mode)
 {
-    unsigned long phys_offset = pfl->fl_mem;
-    int i;
-
-    if (rom_mode)
-        phys_offset |= pfl->off | IO_MEM_ROMD;
-    pfl->rom_mode = rom_mode;
-
-    for (i = 0; i < pfl->mappings; i++)
-        cpu_register_physical_memory(pfl->base + i * pfl->chip_len,
-                                     pfl->chip_len, phys_offset);
+    memory_region_rom_device_set_readable(pfl->orig_mem, rom_mode);
 }
 
 static void pflash_timer (void *opaque)
@@ -538,28 +553,20 @@
     pflash_write(pfl, addr, value, 4, 0);
 }
 
-static CPUWriteMemoryFunc * const pflash_write_ops_be[] = {
-    &pflash_writeb_be,
-    &pflash_writew_be,
-    &pflash_writel_be,
+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 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,
+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,13 +605,12 @@
     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, MemoryRegion *mem,
                                 BlockDriverState *bs, uint32_t sector_len,
                                 int nb_blocs, int nb_mappings, int width,
                                 uint16_t id0, uint16_t id1,
                                 uint16_t id2, uint16_t id3,
-                                uint16_t unlock_addr0, uint16_t unlock_addr1,
-                                int be)
+                                uint16_t unlock_addr0, uint16_t unlock_addr1)
 {
     pflash_t *pfl;
     int32_t chip_len;
@@ -619,31 +625,22 @@
 #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;
+    pfl->storage = memory_region_get_ram_ptr(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;
         }
     }
+    pflash_setup_mappings(pfl, mem);
+    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 c563c6e..8f6ea42 100644
--- a/hw/piix_pci.c
+++ b/hw/piix_pci.c
@@ -142,6 +142,7 @@
     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 @@
             d->smram_enabled = false;
         }
     }
+    memory_region_transaction_commit();
 }
 
 static void i440fx_set_smm(int val, void *arg)
@@ -235,9 +237,16 @@
 {
     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);
 
-    pci_host_data_register_ioport(0xcfc, s);
+    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);
+
     return 0;
 }
 
diff --git a/hw/ppc405_boards.c b/hw/ppc405_boards.c
index dec165e..1eb807c 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,9 @@
     ppc4xx_bd_info_t bd;
     CPUPPCState *env;
     qemu_irq *pic;
-    ram_addr_t sram_offset, bios_offset, bdloc;
+    ram_addr_t sram_offset, bdloc;
+    MemoryRegion *address_space_mem = get_system_memory();
+    MemoryRegion *bios = g_new(MemoryRegion, 1);
     MemoryRegion *ram_memories = g_malloc(2 * sizeof(*ram_memories));
     target_phys_addr_t ram_bases[2], ram_sizes[2];
     target_ulong sram_size;
@@ -224,18 +227,18 @@
     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);
+        memory_region_init_rom_device(bios, &pflash_cfi02_ops_be,
+                                      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), bios,
                               dinfo->bdrv, 65536, fl_sectors, 1,
-                              2, 0x0001, 0x22DA, 0x0000, 0x0000, 0x555, 0x2AA,
-                              1);
+                              2, 0x0001, 0x22DA, 0x0000, 0x0000, 0x555, 0x2AA);
         fl_idx++;
     } else
 #endif
@@ -243,12 +246,12 @@
 #ifdef DEBUG_BOARD_INIT
         printf("Load BIOS from file\n");
 #endif
-        bios_offset = qemu_ram_alloc(NULL, "ef405ep.bios", BIOS_SIZE);
+        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 @@
             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(address_space_mem, (uint32_t)(-bios_size),
+                                    bios);
     }
     /* Register FPGA */
 #ifdef DEBUG_BOARD_INIT
@@ -507,7 +511,9 @@
 {
     char *filename;
     qemu_irq *pic;
-    ram_addr_t bios_offset;
+    MemoryRegion *address_space_mem = get_system_memory();
+    MemoryRegion *bios = g_new(MemoryRegion, 1);
+    MemoryRegion *flash = g_new(MemoryRegion, 1);
     MemoryRegion *ram_memories = g_malloc(2 * sizeof(*ram_memories));
     target_phys_addr_t ram_bases[2], ram_sizes[2];
     long bios_size;
@@ -544,17 +550,17 @@
         /* 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);
+        memory_region_init_rom_device(bios, &pflash_cfi02_ops_be,
+                                      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), bios,
                               dinfo->bdrv, 65536, fl_sectors, 1,
-                              4, 0x0001, 0x22DA, 0x0000, 0x0000, 0x555, 0x2AA,
-                              1);
+                              4, 0x0001, 0x22DA, 0x0000, 0x0000, 0x555, 0x2AA);
         fl_idx++;
     } else
 #endif
@@ -564,10 +570,10 @@
 #endif
         if (bios_name == NULL)
             bios_name = BIOS_FILENAME;
-        bios_offset = qemu_ram_alloc(NULL, "taihu_405ep.bios", BIOS_SIZE);
+        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 +584,9 @@
             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(address_space_mem,
+                                    (uint32_t)(-bios_size), bios);
     }
     /* Register Linux flash */
     dinfo = drive_get(IF_PFLASH, 0, fl_idx);
@@ -590,15 +597,15 @@
         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,
+        memory_region_init_rom_device(flash, &pflash_cfi02_ops_be,
+                                      NULL, "taihu_405ep.flash", bios_size);
+        pflash_cfi02_register(0xfc000000, flash,
                               dinfo->bdrv, 65536, fl_sectors, 1,
-                              4, 0x0001, 0x22DA, 0x0000, 0x0000, 0x555, 0x2AA,
-                              1);
+                              4, 0x0001, 0x22DA, 0x0000, 0x0000, 0x555, 0x2AA);
         fl_idx++;
     }
     /* Register CLPD & LCD display */
diff --git a/hw/ppc4xx_pci.c b/hw/ppc4xx_pci.c
index 52e2663..339b38e 100644
--- a/hw/ppc4xx_pci.c
+++ b/hw/ppc4xx_pci.c
@@ -368,10 +368,12 @@
     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/ppc_newworld.c b/hw/ppc_newworld.c
index 4727e07..fbd443d 100644
--- a/hw/ppc_newworld.c
+++ b/hw/ppc_newworld.c
@@ -146,6 +146,7 @@
     MacIONVRAMState *nvr;
     int bios_size;
     MemoryRegion *pic_mem, *dbdma_mem, *cuda_mem, *escc_mem;
+    MemoryRegion *escc_bar = g_new(MemoryRegion, 1);
     MemoryRegion *ide_mem[3];
     int ppc_boot_device;
     DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
@@ -328,6 +329,8 @@
 
     escc_mem = escc_init(0x80013000, pic[0x25], pic[0x24],
                          serial_hds[0], serial_hds[1], ESCC_CLOCK, 4);
+    memory_region_init_alias(escc_bar, "escc-bar",
+                             escc_mem, 0, memory_region_size(escc_mem));
 
     for(i = 0; i < nb_nics; i++)
         pci_nic_init_nofail(&nd_table[i], "ne2k_pci", NULL);
@@ -350,7 +353,7 @@
     adb_mouse_init(&adb_bus);
 
     macio_init(pci_bus, PCI_DEVICE_ID_APPLE_UNI_N_KEYL, 0, pic_mem,
-               dbdma_mem, cuda_mem, NULL, 3, ide_mem, escc_mem);
+               dbdma_mem, cuda_mem, NULL, 3, ide_mem, escc_bar);
 
     if (usb_enabled) {
         usb_ohci_init_pci(pci_bus, -1);
diff --git a/hw/ppc_oldworld.c b/hw/ppc_oldworld.c
index 0071fc9..235d2ef 100644
--- a/hw/ppc_oldworld.c
+++ b/hw/ppc_oldworld.c
@@ -83,7 +83,7 @@
     MacIONVRAMState *nvr;
     int bios_size;
     MemoryRegion *pic_mem, *dbdma_mem, *cuda_mem;
-    MemoryRegion *escc_mem, *ide_mem[2];
+    MemoryRegion *escc_mem, *escc_bar = g_new(MemoryRegion, 1), *ide_mem[2];
     uint16_t ppc_boot_device;
     DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
     void *fw_cfg;
@@ -241,6 +241,8 @@
 
     escc_mem = escc_init(0x80013000, pic[0x0f], pic[0x10], serial_hds[0],
                                serial_hds[1], ESCC_CLOCK, 4);
+    memory_region_init_alias(escc_bar, "escc-bar",
+                             escc_mem, 0, memory_region_size(escc_mem));
 
     for(i = 0; i < nb_nics; i++)
         pci_nic_init_nofail(&nd_table[i], "ne2k_pci", NULL);
@@ -269,7 +271,7 @@
     pmac_format_nvram_partition(nvr, 0x2000);
 
     macio_init(pci_bus, PCI_DEVICE_ID_APPLE_343S1201, 1, pic_mem,
-               dbdma_mem, cuda_mem, nvr, 2, ide_mem, escc_mem);
+               dbdma_mem, cuda_mem, nvr, 2, ide_mem, escc_bar);
 
     if (usb_enabled) {
         usb_ohci_init_pci(pci_bus, -1);
diff --git a/hw/ppce500_pci.c b/hw/ppce500_pci.c
index 4390aeb..2db365d 100644
--- a/hw/ppce500_pci.c
+++ b/hw/ppce500_pci.c
@@ -79,8 +79,6 @@
     uint32_t gasket_time;
     qemu_irq irq[4];
     /* mmio maps */
-    int cfgaddr;
-    int cfgdata;
     int reg;
 };
 
@@ -268,18 +266,18 @@
     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 @@
 
     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 c36232a..55e4e25 100644
--- a/hw/prep_pci.c
+++ b/hw/prep_pci.c
@@ -125,9 +125,15 @@
                               address_space_io,
                               0, 4);
 
-    pci_host_conf_register_ioport(0xcf8, 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);
 
-    pci_host_data_register_ioport(0xcfc, s);
+    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/r2d.c b/hw/r2d.c
index 96a7ff8..41aa2c2 100644
--- a/hw/r2d.c
+++ b/hw/r2d.c
@@ -235,6 +235,7 @@
     qemu_irq *irq;
     DriveInfo *dinfo;
     int i;
+    MemoryRegion *flash = g_new(MemoryRegion, 1);
 
     if (!cpu_model)
         cpu_model = "SH7751R";
@@ -267,11 +268,13 @@
 
     /* onboard flash memory */
     dinfo = drive_get(IF_PFLASH, 0, 0);
-    pflash_cfi02_register(0x0, qemu_ram_alloc(NULL, "r2d.flash", FLASH_SIZE),
+    memory_region_init_rom_device(flash, &pflash_cfi02_ops_le,
+                                  NULL, "r2d.flash", FLASH_SIZE);
+    pflash_cfi02_register(0x0, flash,
                           dinfo ? dinfo->bdrv : NULL, (16 * 1024),
                           FLASH_SIZE >> 16,
                           1, 4, 0x0000, 0x0000, 0x0000, 0x0000,
-                          0x555, 0x2aa, 0);
+                          0x555, 0x2aa);
 
     /* NIC: rtl8139 on-board, and 2 slots. */
     for (i = 0; i < nb_nics; i++)
diff --git a/hw/stellaris.c b/hw/stellaris.c
index 9b0db7f..2bf1c23 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 @@
         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 @@
 
     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 f9bd3da..d5613ff 100644
--- a/hw/stellaris_enet.c
+++ b/hw/stellaris_enet.c
@@ -69,7 +69,7 @@
     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 @@
     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 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 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 @@
 
     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 @@
 {
     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 f39768b..6e89f06 100644
--- a/hw/sysbus.c
+++ b/hw/sysbus.c
@@ -256,3 +256,32 @@
 
     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 b87c6c5..b3e1f99 100644
--- a/hw/sysbus.h
+++ b/hw/sysbus.h
@@ -57,6 +57,14 @@
 
 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/unin_pci.c b/hw/unin_pci.c
index f896f8c..600cd1e 100644
--- a/hw/unin_pci.c
+++ b/hw/unin_pci.c
@@ -41,7 +41,6 @@
 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 @@
     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_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/virtex_ml507.c b/hw/virtex_ml507.c
index 333050c..aa9e512 100644
--- a/hw/virtex_ml507.c
+++ b/hw/virtex_ml507.c
@@ -196,7 +196,7 @@
     target_phys_addr_t ram_base = 0;
     DriveInfo *dinfo;
     ram_addr_t phys_ram;
-    ram_addr_t phys_flash;
+    MemoryRegion *phys_flash = g_new(MemoryRegion, 1);
     qemu_irq irq[32], *cpu_irq;
     clk_setup_t clk_setup[7];
     int kernel_size;
@@ -215,12 +215,13 @@
     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);
+    memory_region_init_rom_device(phys_flash, &pflash_cfi01_ops_be,
+                                  NULL, "virtex.flash", FLASH_SIZE);
     dinfo = drive_get(IF_PFLASH, 0, 0);
     pflash_cfi01_register(0xfc000000, phys_flash,
                           dinfo ? dinfo->bdrv : NULL, (64 * 1024),
                           FLASH_SIZE >> 16,
-                          1, 0x89, 0x18, 0x0000, 0x0, 1);
+                          1, 0x89, 0x18, 0x0000, 0x0);
 
     cpu_irq = (qemu_irq *) &env->irq_inputs[PPC40x_INPUT_INT];
     dev = xilinx_intc_create(0x81800000, cpu_irq[0], 0);
diff --git a/hw/z2.c b/hw/z2.c
index f93a1bf..d7b8d53 100644
--- a/hw/z2.c
+++ b/hw/z2.c
@@ -280,10 +280,11 @@
     uint32_t sector_len = 0x10000;
     PXA2xxState *cpu;
     DriveInfo *dinfo;
-    int be;
+    const MemoryRegionOps *flash_ops;
     void *z2_lcd;
     i2c_bus *bus;
     DeviceState *wm;
+    MemoryRegion *flash = g_new(MemoryRegion, 1);
 
     if (!cpu_model) {
         cpu_model = "pxa270-c5";
@@ -293,9 +294,9 @@
     cpu = pxa270_init(z2_binfo.ram_size, cpu_model);
 
 #ifdef TARGET_WORDS_BIGENDIAN
-    be = 1;
+    flash_ops = &pflash_cfi01_ops_be;
 #else
-    be = 0;
+    flash_ops = &pflash_cfi01_ops_le;
 #endif
     dinfo = drive_get(IF_PFLASH, 0, 0);
     if (!dinfo) {
@@ -304,11 +305,11 @@
         exit(1);
     }
 
-    if (!pflash_cfi01_register(Z2_FLASH_BASE,
-                               qemu_ram_alloc(NULL, "z2.flash0", Z2_FLASH_SIZE),
+    memory_region_init_rom_device(flash, flash_ops,
+                                  NULL, "z2.flash0", Z2_FLASH_SIZE);
+    if (!pflash_cfi01_register(Z2_FLASH_BASE, flash,
                                dinfo->bdrv, sector_len,
-                               Z2_FLASH_SIZE / sector_len, 4, 0, 0, 0, 0,
-                               be)) {
+                               Z2_FLASH_SIZE / sector_len, 4, 0, 0, 0, 0)) {
         fprintf(stderr, "qemu: Error registering flash memory.\n");
         exit(1);
     }
diff --git a/rwhandler.c b/rwhandler.c
deleted file mode 100644
index bb2238f..0000000
--- a/rwhandler.c
+++ /dev/null
@@ -1,87 +0,0 @@
-#include "rwhandler.h"
-#include "ioport.h"
-#include "cpu-all.h"
-
-#define RWHANDLER_WRITE(name, len, type) \
-static void name(void *opaque, type addr, uint32_t value) \
-{\
-    struct ReadWriteHandler *handler = opaque;\
-    handler->write(handler, addr, value, len);\
-}
-
-#define RWHANDLER_READ(name, len, type) \
-static uint32_t name(void *opaque, type addr) \
-{ \
-    struct ReadWriteHandler *handler = opaque; \
-    return handler->read(handler, addr, len); \
-}
-
-RWHANDLER_WRITE(cpu_io_memory_simple_writeb, 1, target_phys_addr_t);
-RWHANDLER_READ(cpu_io_memory_simple_readb, 1, target_phys_addr_t);
-RWHANDLER_WRITE(cpu_io_memory_simple_writew, 2, target_phys_addr_t);
-RWHANDLER_READ(cpu_io_memory_simple_readw, 2, target_phys_addr_t);
-RWHANDLER_WRITE(cpu_io_memory_simple_writel, 4, target_phys_addr_t);
-RWHANDLER_READ(cpu_io_memory_simple_readl, 4, target_phys_addr_t);
-
-static CPUWriteMemoryFunc * const cpu_io_memory_simple_write[] = {
-    &cpu_io_memory_simple_writeb,
-    &cpu_io_memory_simple_writew,
-    &cpu_io_memory_simple_writel,
-};
-
-static CPUReadMemoryFunc * const cpu_io_memory_simple_read[] = {
-    &cpu_io_memory_simple_readb,
-    &cpu_io_memory_simple_readw,
-    &cpu_io_memory_simple_readl,
-};
-
-int cpu_register_io_memory_simple(struct ReadWriteHandler *handler, int endian)
-{
-    if (!handler->read || !handler->write) {
-        return -1;
-    }
-    return cpu_register_io_memory(cpu_io_memory_simple_read,
-                                  cpu_io_memory_simple_write,
-                                  handler, endian);
-}
-
-RWHANDLER_WRITE(ioport_simple_writeb, 1, uint32_t);
-RWHANDLER_READ(ioport_simple_readb, 1, uint32_t);
-RWHANDLER_WRITE(ioport_simple_writew, 2, uint32_t);
-RWHANDLER_READ(ioport_simple_readw, 2, uint32_t);
-RWHANDLER_WRITE(ioport_simple_writel, 4, uint32_t);
-RWHANDLER_READ(ioport_simple_readl, 4, uint32_t);
-
-int register_ioport_simple(ReadWriteHandler* handler,
-                           pio_addr_t start, int length, int size)
-{
-    IOPortWriteFunc *write;
-    IOPortReadFunc *read;
-    int r;
-    switch (size) {
-    case 1:
-        write = ioport_simple_writeb;
-        read = ioport_simple_readb;
-        break;
-    case 2:
-        write = ioport_simple_writew;
-        read = ioport_simple_readw;
-        break;
-    default:
-        write = ioport_simple_writel;
-        read = ioport_simple_readl;
-    }
-    if (handler->write) {
-        r = register_ioport_write(start, length, size, write, handler);
-        if (r < 0) {
-            return r;
-        }
-    }
-    if (handler->read) {
-        r = register_ioport_read(start, length, size, read, handler);
-        if (r < 0) {
-            return r;
-        }
-    }
-    return 0;
-}
diff --git a/rwhandler.h b/rwhandler.h
deleted file mode 100644
index b2a5790..0000000
--- a/rwhandler.h
+++ /dev/null
@@ -1,27 +0,0 @@
-#ifndef READ_WRITE_HANDLER_H
-#define READ_WRITE_HANDLER_H
-
-#include "qemu-common.h"
-#include "ioport.h"
-
-typedef struct ReadWriteHandler ReadWriteHandler;
-
-/* len is guaranteed to be one of 1, 2 or 4, addr is guaranteed to fit in an
- * appropriate type (io/memory/etc). They do not need to be range checked. */
-typedef void WriteHandlerFunc(ReadWriteHandler *, pcibus_t addr,
-                              uint32_t value, int len);
-typedef uint32_t ReadHandlerFunc(ReadWriteHandler *, pcibus_t addr, int len);
-
-struct ReadWriteHandler {
-    WriteHandlerFunc *write;
-    ReadHandlerFunc *read;
-};
-
-/* Helpers for when we want to use a single routine with length. */
-/* CPU memory handler: both read and write must be present. */
-int cpu_register_io_memory_simple(ReadWriteHandler *, int endian);
-/* io port handler: can supply only read or write handlers. */
-int register_ioport_simple(ReadWriteHandler *,
-                           pio_addr_t start, int length, int size);
-
-#endif