summary refs log tree commit diff stats
path: root/hw
diff options
context:
space:
mode:
Diffstat (limited to 'hw')
-rw-r--r--hw/9pfs/virtio-9p-debug.c5
-rw-r--r--hw/9pfs/virtio-9p-device.c173
-rw-r--r--hw/9pfs/virtio-9p-local.c138
-rw-r--r--hw/9pfs/virtio-9p-posix-acl.c22
-rw-r--r--hw/9pfs/virtio-9p-xattr-user.c11
-rw-r--r--hw/9pfs/virtio-9p-xattr.c7
-rw-r--r--hw/9pfs/virtio-9p-xattr.h9
-rw-r--r--hw/9pfs/virtio-9p.c165
-rw-r--r--hw/9pfs/virtio-9p.h7
-rw-r--r--hw/ide/core.c7
-rw-r--r--hw/multiboot.c2
-rw-r--r--hw/pc.c9
-rw-r--r--hw/ppce500_mpc8544ds.c2
-rw-r--r--hw/qxl.c4
-rw-r--r--hw/scsi-bus.c6
-rw-r--r--hw/sga.c56
-rw-r--r--hw/vga-isa.c1
-rw-r--r--hw/virtio-pci.c57
-rw-r--r--hw/virtio-pci.h43
19 files changed, 440 insertions, 284 deletions
diff --git a/hw/9pfs/virtio-9p-debug.c b/hw/9pfs/virtio-9p-debug.c
index 6b18842fd4..4636ad51f0 100644
--- a/hw/9pfs/virtio-9p-debug.c
+++ b/hw/9pfs/virtio-9p-debug.c
@@ -10,8 +10,9 @@
  * the COPYING file in the top-level directory.
  *
  */
-#include "virtio.h"
-#include "pc.h"
+
+#include "hw/virtio.h"
+#include "hw/pc.h"
 #include "virtio-9p.h"
 #include "virtio-9p-debug.h"
 
diff --git a/hw/9pfs/virtio-9p-device.c b/hw/9pfs/virtio-9p-device.c
new file mode 100644
index 0000000000..a2b6acc408
--- /dev/null
+++ b/hw/9pfs/virtio-9p-device.c
@@ -0,0 +1,173 @@
+/*
+ * Virtio 9p backend
+ *
+ * Copyright IBM, Corp. 2010
+ *
+ * Authors:
+ *  Anthony Liguori   <aliguori@us.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.  See
+ * the COPYING file in the top-level directory.
+ *
+ */
+
+#include "hw/virtio.h"
+#include "hw/pc.h"
+#include "qemu_socket.h"
+#include "hw/virtio-pci.h"
+#include "virtio-9p.h"
+#include "fsdev/qemu-fsdev.h"
+#include "virtio-9p-xattr.h"
+
+static uint32_t virtio_9p_get_features(VirtIODevice *vdev, uint32_t features)
+{
+    features |= 1 << VIRTIO_9P_MOUNT_TAG;
+    return features;
+}
+
+static V9fsState *to_virtio_9p(VirtIODevice *vdev)
+{
+    return (V9fsState *)vdev;
+}
+
+static void virtio_9p_get_config(VirtIODevice *vdev, uint8_t *config)
+{
+    struct virtio_9p_config *cfg;
+    V9fsState *s = to_virtio_9p(vdev);
+
+    cfg = qemu_mallocz(sizeof(struct virtio_9p_config) +
+                        s->tag_len);
+    stw_raw(&cfg->tag_len, s->tag_len);
+    memcpy(cfg->tag, s->tag, s->tag_len);
+    memcpy(config, cfg, s->config_size);
+    qemu_free(cfg);
+}
+
+VirtIODevice *virtio_9p_init(DeviceState *dev, V9fsConf *conf)
+ {
+    V9fsState *s;
+    int i, len;
+    struct stat stat;
+    FsTypeEntry *fse;
+
+
+    s = (V9fsState *)virtio_common_init("virtio-9p",
+                                    VIRTIO_ID_9P,
+                                    sizeof(struct virtio_9p_config)+
+                                    MAX_TAG_LEN,
+                                    sizeof(V9fsState));
+
+    /* initialize pdu allocator */
+    QLIST_INIT(&s->free_list);
+    for (i = 0; i < (MAX_REQ - 1); i++) {
+        QLIST_INSERT_HEAD(&s->free_list, &s->pdus[i], next);
+    }
+
+    s->vq = virtio_add_queue(&s->vdev, MAX_REQ, handle_9p_output);
+
+    fse = get_fsdev_fsentry(conf->fsdev_id);
+
+    if (!fse) {
+        /* We don't have a fsdev identified by fsdev_id */
+        fprintf(stderr, "Virtio-9p device couldn't find fsdev with the "
+                "id = %s\n", conf->fsdev_id ? conf->fsdev_id : "NULL");
+        exit(1);
+    }
+
+    if (!fse->path || !conf->tag) {
+        /* we haven't specified a mount_tag or the path */
+        fprintf(stderr, "fsdev with id %s needs path "
+                "and Virtio-9p device needs mount_tag arguments\n",
+                conf->fsdev_id);
+        exit(1);
+    }
+
+    if (!strcmp(fse->security_model, "passthrough")) {
+        /* Files on the Fileserver set to client user credentials */
+        s->ctx.fs_sm = SM_PASSTHROUGH;
+        s->ctx.xops = passthrough_xattr_ops;
+    } else if (!strcmp(fse->security_model, "mapped")) {
+        /* Files on the fileserver are set to QEMU credentials.
+         * Client user credentials are saved in extended attributes.
+         */
+        s->ctx.fs_sm = SM_MAPPED;
+        s->ctx.xops = mapped_xattr_ops;
+    } else if (!strcmp(fse->security_model, "none")) {
+        /*
+         * Files on the fileserver are set to QEMU credentials.
+         */
+        s->ctx.fs_sm = SM_NONE;
+        s->ctx.xops = none_xattr_ops;
+    } else {
+        fprintf(stderr, "Default to security_model=none. You may want"
+                " enable advanced security model using "
+                "security option:\n\t security_model=passthrough\n\t "
+                "security_model=mapped\n");
+        s->ctx.fs_sm = SM_NONE;
+        s->ctx.xops = none_xattr_ops;
+    }
+
+    if (lstat(fse->path, &stat)) {
+        fprintf(stderr, "share path %s does not exist\n", fse->path);
+        exit(1);
+    } else if (!S_ISDIR(stat.st_mode)) {
+        fprintf(stderr, "share path %s is not a directory\n", fse->path);
+        exit(1);
+    }
+
+    s->ctx.fs_root = qemu_strdup(fse->path);
+    len = strlen(conf->tag);
+    if (len > MAX_TAG_LEN) {
+        len = MAX_TAG_LEN;
+    }
+    /* s->tag is non-NULL terminated string */
+    s->tag = qemu_malloc(len);
+    memcpy(s->tag, conf->tag, len);
+    s->tag_len = len;
+    s->ctx.uid = -1;
+
+    s->ops = fse->ops;
+    s->vdev.get_features = virtio_9p_get_features;
+    s->config_size = sizeof(struct virtio_9p_config) +
+                        s->tag_len;
+    s->vdev.get_config = virtio_9p_get_config;
+
+    return &s->vdev;
+}
+
+static int virtio_9p_init_pci(PCIDevice *pci_dev)
+{
+    VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
+    VirtIODevice *vdev;
+
+    vdev = virtio_9p_init(&pci_dev->qdev, &proxy->fsconf);
+    vdev->nvectors = proxy->nvectors;
+    virtio_init_pci(proxy, vdev,
+                    PCI_VENDOR_ID_REDHAT_QUMRANET,
+                    0x1009,
+                    0x2,
+                    0x00);
+    /* make the actual value visible */
+    proxy->nvectors = vdev->nvectors;
+    return 0;
+}
+
+static PCIDeviceInfo virtio_9p_info = {
+    .qdev.name = "virtio-9p-pci",
+    .qdev.size = sizeof(VirtIOPCIProxy),
+    .init      = virtio_9p_init_pci,
+    .qdev.props = (Property[]) {
+        DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 2),
+        DEFINE_VIRTIO_COMMON_FEATURES(VirtIOPCIProxy, host_features),
+        DEFINE_PROP_STRING("mount_tag", VirtIOPCIProxy, fsconf.tag),
+        DEFINE_PROP_STRING("fsdev", VirtIOPCIProxy, fsconf.fsdev_id),
+        DEFINE_PROP_END_OF_LIST(),
+    }
+};
+
+static void virtio_9p_register_devices(void)
+{
+    pci_qdev_register(&virtio_9p_info);
+}
+
+device_init(virtio_9p_register_devices)
diff --git a/hw/9pfs/virtio-9p-local.c b/hw/9pfs/virtio-9p-local.c
index 0a015de9a5..77904c37bd 100644
--- a/hw/9pfs/virtio-9p-local.c
+++ b/hw/9pfs/virtio-9p-local.c
@@ -10,7 +10,8 @@
  * the COPYING file in the top-level directory.
  *
  */
-#include "virtio.h"
+
+#include "hw/virtio.h"
 #include "virtio-9p.h"
 #include "virtio-9p-xattr.h"
 #include <arpa/inet.h>
@@ -24,7 +25,8 @@
 static int local_lstat(FsContext *fs_ctx, const char *path, struct stat *stbuf)
 {
     int err;
-    err =  lstat(rpath(fs_ctx, path), stbuf);
+    char buffer[PATH_MAX];
+    err =  lstat(rpath(fs_ctx, path, buffer), stbuf);
     if (err) {
         return err;
     }
@@ -34,19 +36,19 @@ static int local_lstat(FsContext *fs_ctx, const char *path, struct stat *stbuf)
         gid_t tmp_gid;
         mode_t tmp_mode;
         dev_t tmp_dev;
-        if (getxattr(rpath(fs_ctx, path), "user.virtfs.uid", &tmp_uid,
+        if (getxattr(rpath(fs_ctx, path, buffer), "user.virtfs.uid", &tmp_uid,
                     sizeof(uid_t)) > 0) {
             stbuf->st_uid = tmp_uid;
         }
-        if (getxattr(rpath(fs_ctx, path), "user.virtfs.gid", &tmp_gid,
+        if (getxattr(rpath(fs_ctx, path, buffer), "user.virtfs.gid", &tmp_gid,
                     sizeof(gid_t)) > 0) {
             stbuf->st_gid = tmp_gid;
         }
-        if (getxattr(rpath(fs_ctx, path), "user.virtfs.mode", &tmp_mode,
-                    sizeof(mode_t)) > 0) {
+        if (getxattr(rpath(fs_ctx, path, buffer), "user.virtfs.mode",
+                    &tmp_mode, sizeof(mode_t)) > 0) {
             stbuf->st_mode = tmp_mode;
         }
-        if (getxattr(rpath(fs_ctx, path), "user.virtfs.rdev", &tmp_dev,
+        if (getxattr(rpath(fs_ctx, path, buffer), "user.virtfs.rdev", &tmp_dev,
                         sizeof(dev_t)) > 0) {
                 stbuf->st_rdev = tmp_dev;
         }
@@ -91,10 +93,12 @@ static int local_set_xattr(const char *path, FsCred *credp)
 static int local_post_create_passthrough(FsContext *fs_ctx, const char *path,
         FsCred *credp)
 {
-    if (chmod(rpath(fs_ctx, path), credp->fc_mode & 07777) < 0) {
+    char buffer[PATH_MAX];
+    if (chmod(rpath(fs_ctx, path, buffer), credp->fc_mode & 07777) < 0) {
         return -1;
     }
-    if (lchown(rpath(fs_ctx, path), credp->fc_uid, credp->fc_gid) < 0) {
+    if (lchown(rpath(fs_ctx, path, buffer), credp->fc_uid,
+                credp->fc_gid) < 0) {
         /*
          * If we fail to change ownership and if we are
          * using security model none. Ignore the error
@@ -110,9 +114,10 @@ static ssize_t local_readlink(FsContext *fs_ctx, const char *path,
         char *buf, size_t bufsz)
 {
     ssize_t tsize = -1;
+    char buffer[PATH_MAX];
     if (fs_ctx->fs_sm == SM_MAPPED) {
         int fd;
-        fd = open(rpath(fs_ctx, path), O_RDONLY);
+        fd = open(rpath(fs_ctx, path, buffer), O_RDONLY);
         if (fd == -1) {
             return -1;
         }
@@ -123,7 +128,7 @@ static ssize_t local_readlink(FsContext *fs_ctx, const char *path,
         return tsize;
     } else if ((fs_ctx->fs_sm == SM_PASSTHROUGH) ||
                (fs_ctx->fs_sm == SM_NONE)) {
-        tsize = readlink(rpath(fs_ctx, path), buf, bufsz);
+        tsize = readlink(rpath(fs_ctx, path, buffer), buf, bufsz);
     }
     return tsize;
 }
@@ -140,12 +145,14 @@ static int local_closedir(FsContext *ctx, DIR *dir)
 
 static int local_open(FsContext *ctx, const char *path, int flags)
 {
-    return open(rpath(ctx, path), flags);
+    char buffer[PATH_MAX];
+    return open(rpath(ctx, path, buffer), flags);
 }
 
 static DIR *local_opendir(FsContext *ctx, const char *path)
 {
-    return opendir(rpath(ctx, path));
+    char buffer[PATH_MAX];
+    return opendir(rpath(ctx, path, buffer));
 }
 
 static void local_rewinddir(FsContext *ctx, DIR *dir)
@@ -200,11 +207,12 @@ static ssize_t local_pwritev(FsContext *ctx, int fd, const struct iovec *iov,
 
 static int local_chmod(FsContext *fs_ctx, const char *path, FsCred *credp)
 {
+    char buffer[PATH_MAX];
     if (fs_ctx->fs_sm == SM_MAPPED) {
-        return local_set_xattr(rpath(fs_ctx, path), credp);
+        return local_set_xattr(rpath(fs_ctx, path, buffer), credp);
     } else if ((fs_ctx->fs_sm == SM_PASSTHROUGH) ||
                (fs_ctx->fs_sm == SM_NONE)) {
-        return chmod(rpath(fs_ctx, path), credp->fc_mode);
+        return chmod(rpath(fs_ctx, path, buffer), credp->fc_mode);
     }
     return -1;
 }
@@ -213,21 +221,24 @@ static int local_mknod(FsContext *fs_ctx, const char *path, FsCred *credp)
 {
     int err = -1;
     int serrno = 0;
+    char buffer[PATH_MAX];
 
     /* Determine the security model */
     if (fs_ctx->fs_sm == SM_MAPPED) {
-        err = mknod(rpath(fs_ctx, path), SM_LOCAL_MODE_BITS|S_IFREG, 0);
+        err = mknod(rpath(fs_ctx, path, buffer),
+                SM_LOCAL_MODE_BITS|S_IFREG, 0);
         if (err == -1) {
             return err;
         }
-        local_set_xattr(rpath(fs_ctx, path), credp);
+        local_set_xattr(rpath(fs_ctx, path, buffer), credp);
         if (err == -1) {
             serrno = errno;
             goto err_end;
         }
     } else if ((fs_ctx->fs_sm == SM_PASSTHROUGH) ||
                (fs_ctx->fs_sm == SM_NONE)) {
-        err = mknod(rpath(fs_ctx, path), credp->fc_mode, credp->fc_rdev);
+        err = mknod(rpath(fs_ctx, path, buffer), credp->fc_mode,
+                credp->fc_rdev);
         if (err == -1) {
             return err;
         }
@@ -240,7 +251,7 @@ static int local_mknod(FsContext *fs_ctx, const char *path, FsCred *credp)
     return err;
 
 err_end:
-    remove(rpath(fs_ctx, path));
+    remove(rpath(fs_ctx, path, buffer));
     errno = serrno;
     return err;
 }
@@ -249,22 +260,23 @@ static int local_mkdir(FsContext *fs_ctx, const char *path, FsCred *credp)
 {
     int err = -1;
     int serrno = 0;
+    char buffer[PATH_MAX];
 
     /* Determine the security model */
     if (fs_ctx->fs_sm == SM_MAPPED) {
-        err = mkdir(rpath(fs_ctx, path), SM_LOCAL_DIR_MODE_BITS);
+        err = mkdir(rpath(fs_ctx, path, buffer), SM_LOCAL_DIR_MODE_BITS);
         if (err == -1) {
             return err;
         }
         credp->fc_mode = credp->fc_mode|S_IFDIR;
-        err = local_set_xattr(rpath(fs_ctx, path), credp);
+        err = local_set_xattr(rpath(fs_ctx, path, buffer), credp);
         if (err == -1) {
             serrno = errno;
             goto err_end;
         }
     } else if ((fs_ctx->fs_sm == SM_PASSTHROUGH) ||
                (fs_ctx->fs_sm == SM_NONE)) {
-        err = mkdir(rpath(fs_ctx, path), credp->fc_mode);
+        err = mkdir(rpath(fs_ctx, path, buffer), credp->fc_mode);
         if (err == -1) {
             return err;
         }
@@ -277,7 +289,7 @@ static int local_mkdir(FsContext *fs_ctx, const char *path, FsCred *credp)
     return err;
 
 err_end:
-    remove(rpath(fs_ctx, path));
+    remove(rpath(fs_ctx, path, buffer));
     errno = serrno;
     return err;
 }
@@ -318,23 +330,24 @@ static int local_open2(FsContext *fs_ctx, const char *path, int flags,
     int fd = -1;
     int err = -1;
     int serrno = 0;
+    char buffer[PATH_MAX];
 
     /* Determine the security model */
     if (fs_ctx->fs_sm == SM_MAPPED) {
-        fd = open(rpath(fs_ctx, path), flags, SM_LOCAL_MODE_BITS);
+        fd = open(rpath(fs_ctx, path, buffer), flags, SM_LOCAL_MODE_BITS);
         if (fd == -1) {
             return fd;
         }
         credp->fc_mode = credp->fc_mode|S_IFREG;
         /* Set cleint credentials in xattr */
-        err = local_set_xattr(rpath(fs_ctx, path), credp);
+        err = local_set_xattr(rpath(fs_ctx, path, buffer), credp);
         if (err == -1) {
             serrno = errno;
             goto err_end;
         }
     } else if ((fs_ctx->fs_sm == SM_PASSTHROUGH) ||
                (fs_ctx->fs_sm == SM_NONE)) {
-        fd = open(rpath(fs_ctx, path), flags, credp->fc_mode);
+        fd = open(rpath(fs_ctx, path, buffer), flags, credp->fc_mode);
         if (fd == -1) {
             return fd;
         }
@@ -348,7 +361,7 @@ static int local_open2(FsContext *fs_ctx, const char *path, int flags,
 
 err_end:
     close(fd);
-    remove(rpath(fs_ctx, path));
+    remove(rpath(fs_ctx, path, buffer));
     errno = serrno;
     return err;
 }
@@ -359,12 +372,13 @@ static int local_symlink(FsContext *fs_ctx, const char *oldpath,
 {
     int err = -1;
     int serrno = 0;
+    char buffer[PATH_MAX];
 
     /* Determine the security model */
     if (fs_ctx->fs_sm == SM_MAPPED) {
         int fd;
         ssize_t oldpath_size, write_size;
-        fd = open(rpath(fs_ctx, newpath), O_CREAT|O_EXCL|O_RDWR,
+        fd = open(rpath(fs_ctx, newpath, buffer), O_CREAT|O_EXCL|O_RDWR,
                 SM_LOCAL_MODE_BITS);
         if (fd == -1) {
             return fd;
@@ -384,18 +398,19 @@ static int local_symlink(FsContext *fs_ctx, const char *oldpath,
         close(fd);
         /* Set cleint credentials in symlink's xattr */
         credp->fc_mode = credp->fc_mode|S_IFLNK;
-        err = local_set_xattr(rpath(fs_ctx, newpath), credp);
+        err = local_set_xattr(rpath(fs_ctx, newpath, buffer), credp);
         if (err == -1) {
             serrno = errno;
             goto err_end;
         }
     } else if ((fs_ctx->fs_sm == SM_PASSTHROUGH) ||
                (fs_ctx->fs_sm == SM_NONE)) {
-        err = symlink(oldpath, rpath(fs_ctx, newpath));
+        err = symlink(oldpath, rpath(fs_ctx, newpath, buffer));
         if (err) {
             return err;
         }
-        err = lchown(rpath(fs_ctx, newpath), credp->fc_uid, credp->fc_gid);
+        err = lchown(rpath(fs_ctx, newpath, buffer), credp->fc_uid,
+                credp->fc_gid);
         if (err == -1) {
             /*
              * If we fail to change ownership and if we are
@@ -411,70 +426,45 @@ static int local_symlink(FsContext *fs_ctx, const char *oldpath,
     return err;
 
 err_end:
-    remove(rpath(fs_ctx, newpath));
+    remove(rpath(fs_ctx, newpath, buffer));
     errno = serrno;
     return err;
 }
 
 static int local_link(FsContext *ctx, const char *oldpath, const char *newpath)
 {
-    char *tmp = qemu_strdup(rpath(ctx, oldpath));
-    int err, serrno = 0;
-
-    if (tmp == NULL) {
-        return -ENOMEM;
-    }
-
-    err = link(tmp, rpath(ctx, newpath));
-    if (err == -1) {
-        serrno = errno;
-    }
-
-    qemu_free(tmp);
-
-    if (err == -1) {
-        errno = serrno;
-    }
+    char buffer[PATH_MAX], buffer1[PATH_MAX];
 
-    return err;
+    return link(rpath(ctx, oldpath, buffer), rpath(ctx, newpath, buffer1));
 }
 
 static int local_truncate(FsContext *ctx, const char *path, off_t size)
 {
-    return truncate(rpath(ctx, path), size);
+    char buffer[PATH_MAX];
+    return truncate(rpath(ctx, path, buffer), size);
 }
 
 static int local_rename(FsContext *ctx, const char *oldpath,
                         const char *newpath)
 {
-    char *tmp;
-    int err;
-
-    tmp = qemu_strdup(rpath(ctx, oldpath));
-
-    err = rename(tmp, rpath(ctx, newpath));
-    if (err == -1) {
-        int serrno = errno;
-        qemu_free(tmp);
-        errno = serrno;
-    } else {
-        qemu_free(tmp);
-    }
-
-    return err;
+    char buffer[PATH_MAX], buffer1[PATH_MAX];
 
+    return rename(rpath(ctx, oldpath, buffer), rpath(ctx, newpath, buffer1));
 }
 
 static int local_chown(FsContext *fs_ctx, const char *path, FsCred *credp)
 {
+    char buffer[PATH_MAX];
     if ((credp->fc_uid == -1 && credp->fc_gid == -1) ||
             (fs_ctx->fs_sm == SM_PASSTHROUGH)) {
-        return lchown(rpath(fs_ctx, path), credp->fc_uid, credp->fc_gid);
+        return lchown(rpath(fs_ctx, path, buffer), credp->fc_uid,
+                credp->fc_gid);
     } else if (fs_ctx->fs_sm == SM_MAPPED) {
-        return local_set_xattr(rpath(fs_ctx, path), credp);
+        return local_set_xattr(rpath(fs_ctx, path, buffer), credp);
     } else if ((fs_ctx->fs_sm == SM_PASSTHROUGH) ||
                (fs_ctx->fs_sm == SM_NONE)) {
-        return lchown(rpath(fs_ctx, path), credp->fc_uid, credp->fc_gid);
+        return lchown(rpath(fs_ctx, path, buffer), credp->fc_uid,
+                credp->fc_gid);
     }
     return -1;
 }
@@ -482,12 +472,15 @@ static int local_chown(FsContext *fs_ctx, const char *path, FsCred *credp)
 static int local_utimensat(FsContext *s, const char *path,
                            const struct timespec *buf)
 {
-    return qemu_utimensat(AT_FDCWD, rpath(s, path), buf, AT_SYMLINK_NOFOLLOW);
+    char buffer[PATH_MAX];
+    return qemu_utimensat(AT_FDCWD, rpath(s, path, buffer), buf,
+            AT_SYMLINK_NOFOLLOW);
 }
 
 static int local_remove(FsContext *ctx, const char *path)
 {
-    return remove(rpath(ctx, path));
+    char buffer[PATH_MAX];
+    return remove(rpath(ctx, path, buffer));
 }
 
 static int local_fsync(FsContext *ctx, int fd, int datasync)
@@ -501,7 +494,8 @@ static int local_fsync(FsContext *ctx, int fd, int datasync)
 
 static int local_statfs(FsContext *s, const char *path, struct statfs *stbuf)
 {
-   return statfs(rpath(s, path), stbuf);
+    char buffer[PATH_MAX];
+   return statfs(rpath(s, path, buffer), stbuf);
 }
 
 static ssize_t local_lgetxattr(FsContext *ctx, const char *path,
diff --git a/hw/9pfs/virtio-9p-posix-acl.c b/hw/9pfs/virtio-9p-posix-acl.c
index 575abe86b0..f5b392e180 100644
--- a/hw/9pfs/virtio-9p-posix-acl.c
+++ b/hw/9pfs/virtio-9p-posix-acl.c
@@ -13,7 +13,7 @@
 
 #include <sys/types.h>
 #include <attr/xattr.h>
-#include "virtio.h"
+#include "hw/virtio.h"
 #include "virtio-9p.h"
 #include "fsdev/file-op-9p.h"
 #include "virtio-9p-xattr.h"
@@ -26,7 +26,8 @@
 static ssize_t mp_pacl_getxattr(FsContext *ctx, const char *path,
                                 const char *name, void *value, size_t size)
 {
-    return lgetxattr(rpath(ctx, path), MAP_ACL_ACCESS, value, size);
+    char buffer[PATH_MAX];
+    return lgetxattr(rpath(ctx, path, buffer), MAP_ACL_ACCESS, value, size);
 }
 
 static ssize_t mp_pacl_listxattr(FsContext *ctx, const char *path,
@@ -50,14 +51,17 @@ static ssize_t mp_pacl_listxattr(FsContext *ctx, const char *path,
 static int mp_pacl_setxattr(FsContext *ctx, const char *path, const char *name,
                             void *value, size_t size, int flags)
 {
-    return lsetxattr(rpath(ctx, path), MAP_ACL_ACCESS, value, size, flags);
+    char buffer[PATH_MAX];
+    return lsetxattr(rpath(ctx, path, buffer), MAP_ACL_ACCESS, value,
+            size, flags);
 }
 
 static int mp_pacl_removexattr(FsContext *ctx,
                                const char *path, const char *name)
 {
     int ret;
-    ret  = lremovexattr(rpath(ctx, path), MAP_ACL_ACCESS);
+    char buffer[PATH_MAX];
+    ret  = lremovexattr(rpath(ctx, path, buffer), MAP_ACL_ACCESS);
     if (ret == -1 && errno == ENODATA) {
         /*
          * We don't get ENODATA error when trying to remove a
@@ -73,7 +77,8 @@ static int mp_pacl_removexattr(FsContext *ctx,
 static ssize_t mp_dacl_getxattr(FsContext *ctx, const char *path,
                                 const char *name, void *value, size_t size)
 {
-    return lgetxattr(rpath(ctx, path), MAP_ACL_DEFAULT, value, size);
+    char buffer[PATH_MAX];
+    return lgetxattr(rpath(ctx, path, buffer), MAP_ACL_DEFAULT, value, size);
 }
 
 static ssize_t mp_dacl_listxattr(FsContext *ctx, const char *path,
@@ -97,14 +102,17 @@ static ssize_t mp_dacl_listxattr(FsContext *ctx, const char *path,
 static int mp_dacl_setxattr(FsContext *ctx, const char *path, const char *name,
                             void *value, size_t size, int flags)
 {
-    return lsetxattr(rpath(ctx, path), MAP_ACL_DEFAULT, value, size, flags);
+    char buffer[PATH_MAX];
+    return lsetxattr(rpath(ctx, path, buffer), MAP_ACL_DEFAULT, value,
+            size, flags);
 }
 
 static int mp_dacl_removexattr(FsContext *ctx,
                                const char *path, const char *name)
 {
     int ret;
-    ret  = lremovexattr(rpath(ctx, path), MAP_ACL_DEFAULT);
+    char buffer[PATH_MAX];
+    ret  = lremovexattr(rpath(ctx, path, buffer), MAP_ACL_DEFAULT);
     if (ret == -1 && errno == ENODATA) {
         /*
          * We don't get ENODATA error when trying to remove a
diff --git a/hw/9pfs/virtio-9p-xattr-user.c b/hw/9pfs/virtio-9p-xattr-user.c
index bba13ce643..5044a3e5ab 100644
--- a/hw/9pfs/virtio-9p-xattr-user.c
+++ b/hw/9pfs/virtio-9p-xattr-user.c
@@ -12,7 +12,7 @@
  */
 
 #include <sys/types.h>
-#include "virtio.h"
+#include "hw/virtio.h"
 #include "virtio-9p.h"
 #include "fsdev/file-op-9p.h"
 #include "virtio-9p-xattr.h"
@@ -21,6 +21,7 @@
 static ssize_t mp_user_getxattr(FsContext *ctx, const char *path,
                                 const char *name, void *value, size_t size)
 {
+    char buffer[PATH_MAX];
     if (strncmp(name, "user.virtfs.", 12) == 0) {
         /*
          * Don't allow fetch of user.virtfs namesapce
@@ -29,7 +30,7 @@ static ssize_t mp_user_getxattr(FsContext *ctx, const char *path,
         errno = ENOATTR;
         return -1;
     }
-    return lgetxattr(rpath(ctx, path), name, value, size);
+    return lgetxattr(rpath(ctx, path, buffer), name, value, size);
 }
 
 static ssize_t mp_user_listxattr(FsContext *ctx, const char *path,
@@ -67,6 +68,7 @@ static ssize_t mp_user_listxattr(FsContext *ctx, const char *path,
 static int mp_user_setxattr(FsContext *ctx, const char *path, const char *name,
                             void *value, size_t size, int flags)
 {
+    char buffer[PATH_MAX];
     if (strncmp(name, "user.virtfs.", 12) == 0) {
         /*
          * Don't allow fetch of user.virtfs namesapce
@@ -75,12 +77,13 @@ static int mp_user_setxattr(FsContext *ctx, const char *path, const char *name,
         errno = EACCES;
         return -1;
     }
-    return lsetxattr(rpath(ctx, path), name, value, size, flags);
+    return lsetxattr(rpath(ctx, path, buffer), name, value, size, flags);
 }
 
 static int mp_user_removexattr(FsContext *ctx,
                                const char *path, const char *name)
 {
+    char buffer[PATH_MAX];
     if (strncmp(name, "user.virtfs.", 12) == 0) {
         /*
          * Don't allow fetch of user.virtfs namesapce
@@ -89,7 +92,7 @@ static int mp_user_removexattr(FsContext *ctx,
         errno = EACCES;
         return -1;
     }
-    return lremovexattr(rpath(ctx, path), name);
+    return lremovexattr(rpath(ctx, path, buffer), name);
 }
 
 XattrOperations mapped_user_xattr = {
diff --git a/hw/9pfs/virtio-9p-xattr.c b/hw/9pfs/virtio-9p-xattr.c
index 03c3d3f6bb..bde0b7fb4f 100644
--- a/hw/9pfs/virtio-9p-xattr.c
+++ b/hw/9pfs/virtio-9p-xattr.c
@@ -11,7 +11,7 @@
  *
  */
 
-#include "virtio.h"
+#include "hw/virtio.h"
 #include "virtio-9p.h"
 #include "fsdev/file-op-9p.h"
 #include "virtio-9p-xattr.h"
@@ -66,20 +66,21 @@ ssize_t v9fs_list_xattr(FsContext *ctx, const char *path,
                         void *value, size_t vsize)
 {
     ssize_t size = 0;
+    char buffer[PATH_MAX];
     void *ovalue = value;
     XattrOperations *xops;
     char *orig_value, *orig_value_start;
     ssize_t xattr_len, parsed_len = 0, attr_len;
 
     /* Get the actual len */
-    xattr_len = llistxattr(rpath(ctx, path), value, 0);
+    xattr_len = llistxattr(rpath(ctx, path, buffer), value, 0);
     if (xattr_len <= 0) {
         return xattr_len;
     }
 
     /* Now fetch the xattr and find the actual size */
     orig_value = qemu_malloc(xattr_len);
-    xattr_len = llistxattr(rpath(ctx, path), orig_value, xattr_len);
+    xattr_len = llistxattr(rpath(ctx, path, buffer), orig_value, xattr_len);
 
     /* store the orig pointer */
     orig_value_start = orig_value;
diff --git a/hw/9pfs/virtio-9p-xattr.h b/hw/9pfs/virtio-9p-xattr.h
index 2bbae2dcb5..247e414ebd 100644
--- a/hw/9pfs/virtio-9p-xattr.h
+++ b/hw/9pfs/virtio-9p-xattr.h
@@ -54,20 +54,23 @@ ssize_t pt_listxattr(FsContext *ctx, const char *path, char *name, void *value,
 static inline ssize_t pt_getxattr(FsContext *ctx, const char *path,
                                   const char *name, void *value, size_t size)
 {
-    return lgetxattr(rpath(ctx, path), name, value, size);
+    char buffer[PATH_MAX];
+    return lgetxattr(rpath(ctx, path, buffer), name, value, size);
 }
 
 static inline int pt_setxattr(FsContext *ctx, const char *path,
                               const char *name, void *value,
                               size_t size, int flags)
 {
-    return lsetxattr(rpath(ctx, path), name, value, size, flags);
+    char buffer[PATH_MAX];
+    return lsetxattr(rpath(ctx, path, buffer), name, value, size, flags);
 }
 
 static inline int pt_removexattr(FsContext *ctx,
                                  const char *path, const char *name)
 {
-    return lremovexattr(rpath(ctx, path), name);
+    char buffer[PATH_MAX];
+    return lremovexattr(rpath(ctx, path, buffer), name);
 }
 
 static inline ssize_t notsup_getxattr(FsContext *ctx, const char *path,
diff --git a/hw/9pfs/virtio-9p.c b/hw/9pfs/virtio-9p.c
index b5fc52b3eb..4890df6f75 100644
--- a/hw/9pfs/virtio-9p.c
+++ b/hw/9pfs/virtio-9p.c
@@ -11,9 +11,10 @@
  *
  */
 
-#include "virtio.h"
-#include "pc.h"
+#include "hw/virtio.h"
+#include "hw/pc.h"
 #include "qemu_socket.h"
+#include "hw/virtio-pci.h"
 #include "virtio-9p.h"
 #include "fsdev/qemu-fsdev.h"
 #include "virtio-9p-debug.h"
@@ -194,7 +195,6 @@ static int v9fs_do_open2(V9fsState *s, char *fullname, uid_t uid, gid_t gid,
     cred.fc_uid = uid;
     cred.fc_gid = gid;
     cred.fc_mode = mode & 07777;
-    flags = flags;
 
     return s->ops->open2(&s->ctx, fullname, flags, &cred);
 }
@@ -423,6 +423,22 @@ static void v9fs_string_copy(V9fsString *lhs, V9fsString *rhs)
     v9fs_string_sprintf(lhs, "%s", rhs->data);
 }
 
+/*
+ * Return TRUE if s1 is an ancestor of s2.
+ *
+ * E.g. "a/b" is an ancestor of "a/b/c" but not of "a/bc/d".
+ * As a special case, We treat s1 as ancestor of s2 if they are same!
+ */
+static int v9fs_path_is_ancestor(V9fsString *s1, V9fsString *s2)
+{
+    if (!strncmp(s1->data, s2->data, s1->size)) {
+        if (s2->data[s1->size] == '\0' || s2->data[s1->size] == '/') {
+            return 1;
+        }
+    }
+    return 0;
+}
+
 static size_t v9fs_string_size(V9fsString *str)
 {
     return str->size;
@@ -2805,13 +2821,13 @@ static int v9fs_complete_rename(V9fsState *s, V9fsRenameState *vs)
             for (fidp = s->fid_list; fidp; fidp = fidp->next) {
                 if (vs->fidp == fidp) {
                     /*
-                    * we replace name of this fid towards the end
-                    * so that our below strcmp will work
+                    * we replace name of this fid towards the end so
+                    * that our below v9fs_path_is_ancestor check will
+                    * work
                     */
                     continue;
                 }
-                if (!strncmp(vs->fidp->path.data, fidp->path.data,
-                    strlen(vs->fidp->path.data))) {
+                if (v9fs_path_is_ancestor(&vs->fidp->path, &fidp->path)) {
                     /* replace the name */
                     v9fs_fix_path(&fidp->path, &vs->name,
                                   strlen(vs->fidp->path.data));
@@ -3589,6 +3605,11 @@ static pdu_handler_t *pdu_handlers[] = {
     [P9_TREMOVE] = v9fs_remove,
 };
 
+static void v9fs_op_not_supp(V9fsState *s, V9fsPDU *pdu)
+{
+    complete_pdu(s, pdu, -EOPNOTSUPP);
+}
+
 static void submit_pdu(V9fsState *s, V9fsPDU *pdu)
 {
     pdu_handler_t *handler;
@@ -3596,16 +3617,16 @@ static void submit_pdu(V9fsState *s, V9fsPDU *pdu)
     if (debug_9p_pdu) {
         pprint_pdu(pdu);
     }
-
-    BUG_ON(pdu->id >= ARRAY_SIZE(pdu_handlers));
-
-    handler = pdu_handlers[pdu->id];
-    BUG_ON(handler == NULL);
-
+    if (pdu->id >= ARRAY_SIZE(pdu_handlers) ||
+        (pdu_handlers[pdu->id] == NULL)) {
+        handler = v9fs_op_not_supp;
+    } else {
+        handler = pdu_handlers[pdu->id];
+    }
     handler(s, pdu);
 }
 
-static void handle_9p_output(VirtIODevice *vdev, VirtQueue *vq)
+void handle_9p_output(VirtIODevice *vdev, VirtQueue *vq)
 {
     V9fsState *s = (V9fsState *)vdev;
     V9fsPDU *pdu;
@@ -3629,119 +3650,3 @@ static void handle_9p_output(VirtIODevice *vdev, VirtQueue *vq)
 
     free_pdu(s, pdu);
 }
-
-static uint32_t virtio_9p_get_features(VirtIODevice *vdev, uint32_t features)
-{
-    features |= 1 << VIRTIO_9P_MOUNT_TAG;
-    return features;
-}
-
-static V9fsState *to_virtio_9p(VirtIODevice *vdev)
-{
-    return (V9fsState *)vdev;
-}
-
-static void virtio_9p_get_config(VirtIODevice *vdev, uint8_t *config)
-{
-    struct virtio_9p_config *cfg;
-    V9fsState *s = to_virtio_9p(vdev);
-
-    cfg = qemu_mallocz(sizeof(struct virtio_9p_config) +
-                        s->tag_len);
-    stw_raw(&cfg->tag_len, s->tag_len);
-    memcpy(cfg->tag, s->tag, s->tag_len);
-    memcpy(config, cfg, s->config_size);
-    qemu_free(cfg);
-}
-
-VirtIODevice *virtio_9p_init(DeviceState *dev, V9fsConf *conf)
- {
-    V9fsState *s;
-    int i, len;
-    struct stat stat;
-    FsTypeEntry *fse;
-
-
-    s = (V9fsState *)virtio_common_init("virtio-9p",
-                                    VIRTIO_ID_9P,
-                                    sizeof(struct virtio_9p_config)+
-                                    MAX_TAG_LEN,
-                                    sizeof(V9fsState));
-
-    /* initialize pdu allocator */
-    QLIST_INIT(&s->free_list);
-    for (i = 0; i < (MAX_REQ - 1); i++) {
-	QLIST_INSERT_HEAD(&s->free_list, &s->pdus[i], next);
-    }
-
-    s->vq = virtio_add_queue(&s->vdev, MAX_REQ, handle_9p_output);
-
-    fse = get_fsdev_fsentry(conf->fsdev_id);
-
-    if (!fse) {
-        /* We don't have a fsdev identified by fsdev_id */
-        fprintf(stderr, "Virtio-9p device couldn't find fsdev with the "
-                "id = %s\n", conf->fsdev_id ? conf->fsdev_id : "NULL");
-        exit(1);
-    }
-
-    if (!fse->path || !conf->tag) {
-        /* we haven't specified a mount_tag or the path */
-        fprintf(stderr, "fsdev with id %s needs path "
-                "and Virtio-9p device needs mount_tag arguments\n",
-                conf->fsdev_id);
-        exit(1);
-    }
-
-    if (!strcmp(fse->security_model, "passthrough")) {
-        /* Files on the Fileserver set to client user credentials */
-        s->ctx.fs_sm = SM_PASSTHROUGH;
-        s->ctx.xops = passthrough_xattr_ops;
-    } else if (!strcmp(fse->security_model, "mapped")) {
-        /* Files on the fileserver are set to QEMU credentials.
-         * Client user credentials are saved in extended attributes.
-         */
-        s->ctx.fs_sm = SM_MAPPED;
-        s->ctx.xops = mapped_xattr_ops;
-    } else if (!strcmp(fse->security_model, "none")) {
-        /*
-         * Files on the fileserver are set to QEMU credentials.
-         */
-        s->ctx.fs_sm = SM_NONE;
-        s->ctx.xops = none_xattr_ops;
-    } else {
-        fprintf(stderr, "Default to security_model=none. You may want"
-                " enable advanced security model using "
-                "security option:\n\t security_model=passthrough \n\t "
-                "security_model=mapped\n");
-        s->ctx.fs_sm = SM_NONE;
-        s->ctx.xops = none_xattr_ops;
-    }
-
-    if (lstat(fse->path, &stat)) {
-        fprintf(stderr, "share path %s does not exist\n", fse->path);
-        exit(1);
-    } else if (!S_ISDIR(stat.st_mode)) {
-        fprintf(stderr, "share path %s is not a directory \n", fse->path);
-        exit(1);
-    }
-
-    s->ctx.fs_root = qemu_strdup(fse->path);
-    len = strlen(conf->tag);
-    if (len > MAX_TAG_LEN) {
-        len = MAX_TAG_LEN;
-    }
-    /* s->tag is non-NULL terminated string */
-    s->tag = qemu_malloc(len);
-    memcpy(s->tag, conf->tag, len);
-    s->tag_len = len;
-    s->ctx.uid = -1;
-
-    s->ops = fse->ops;
-    s->vdev.get_features = virtio_9p_get_features;
-    s->config_size = sizeof(struct virtio_9p_config) +
-                        s->tag_len;
-    s->vdev.get_config = virtio_9p_get_config;
-
-    return &s->vdev;
-}
diff --git a/hw/9pfs/virtio-9p.h b/hw/9pfs/virtio-9p.h
index 622928fce5..2bfbe622af 100644
--- a/hw/9pfs/virtio-9p.h
+++ b/hw/9pfs/virtio-9p.h
@@ -101,6 +101,11 @@ enum p9_proto_version {
 #define P9_NOTAG    (u16)(~0)
 #define P9_NOFID    (u32)(~0)
 #define P9_MAXWELEM 16
+static inline const char *rpath(FsContext *ctx, const char *path, char *buffer)
+{
+    snprintf(buffer, PATH_MAX, "%s/%s", ctx->fs_root, path);
+    return buffer;
+}
 
 /*
  * ample room for Twrite/Rread header
@@ -504,4 +509,6 @@ static inline size_t do_pdu_unpack(void *dst, struct iovec *sg, int sg_count,
     return pdu_packunpack(dst, sg, sg_count, offset, size, 0);
 }
 
+extern void handle_9p_output(VirtIODevice *vdev, VirtQueue *vq);
+
 #endif
diff --git a/hw/ide/core.c b/hw/ide/core.c
index 45410e81a2..95beb175b3 100644
--- a/hw/ide/core.c
+++ b/hw/ide/core.c
@@ -430,7 +430,6 @@ void ide_dma_error(IDEState *s)
     s->error = ABRT_ERR;
     s->status = READY_STAT | ERR_STAT;
     ide_set_inactive(s);
-    s->bus->dma->ops->add_status(s->bus->dma, BM_STATUS_INT);
     ide_set_irq(s->bus);
 }
 
@@ -500,8 +499,11 @@ handle_rw_error:
     n = s->nsector;
     s->io_buffer_index = 0;
     s->io_buffer_size = n * 512;
-    if (s->bus->dma->ops->prepare_buf(s->bus->dma, s->is_read) == 0)
+    if (s->bus->dma->ops->prepare_buf(s->bus->dma, s->is_read) == 0) {
+        /* The PRDs were too short. Reset the Active bit, but don't raise an
+         * interrupt. */
         goto eot;
+    }
 
 #ifdef DEBUG_AIO
     printf("ide_dma_cb: sector_num=%" PRId64 " n=%d, is_read=%d\n",
@@ -523,7 +525,6 @@ handle_rw_error:
     return;
 
 eot:
-   s->bus->dma->ops->add_status(s->bus->dma, BM_STATUS_INT);
    ide_set_inactive(s);
 }
 
diff --git a/hw/multiboot.c b/hw/multiboot.c
index 394ed0136e..6e6cfb9531 100644
--- a/hw/multiboot.c
+++ b/hw/multiboot.c
@@ -307,7 +307,7 @@ int load_multiboot(void *fw_cfg,
                                 | MULTIBOOT_FLAGS_MMAP);
     stl_p(bootinfo + MBI_MEM_LOWER,   640);
     stl_p(bootinfo + MBI_MEM_UPPER,   (ram_size / 1024) - 1024);
-    stl_p(bootinfo + MBI_BOOT_DEVICE, 0x8001ffff); /* XXX: use the -boot switch? */
+    stl_p(bootinfo + MBI_BOOT_DEVICE, 0x8000ffff); /* XXX: use the -boot switch? */
     stl_p(bootinfo + MBI_MMAP_ADDR,   ADDR_E820_MAP);
 
     mb_debug("multiboot: mh_entry_addr = %#x\n", mh_entry_addr);
diff --git a/hw/pc.c b/hw/pc.c
index 810619756b..a3e8539dc6 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -1070,6 +1070,15 @@ void pc_vga_init(PCIBus *pci_bus)
             isa_vga_init();
         }
     }
+
+    /*
+     * sga does not suppress normal vga output. So a machine can have both a
+     * vga card and sga manually enabled. Output will be seen on both.
+     * For nographic case, sga is enabled at all times
+     */
+    if (display_type == DT_NOGRAPHIC) {
+        isa_create_simple("sga");
+    }
 }
 
 static void cpu_request_exit(void *opaque, int irq, int level)
diff --git a/hw/ppce500_mpc8544ds.c b/hw/ppce500_mpc8544ds.c
index 17b0165533..6b57fbf597 100644
--- a/hw/ppce500_mpc8544ds.c
+++ b/hw/ppce500_mpc8544ds.c
@@ -275,7 +275,7 @@ static void mpc8544ds_init(ram_addr_t ram_size,
                                 mpic[pci_irq_nrs[0]], mpic[pci_irq_nrs[1]],
                                 mpic[pci_irq_nrs[2]], mpic[pci_irq_nrs[3]],
                                 NULL);
-    pci_bus = (PCIBus *)qdev_get_child_bus(dev, "pci");
+    pci_bus = (PCIBus *)qdev_get_child_bus(dev, "pci.0");
     if (!pci_bus)
         printf("couldn't create PCI controller!\n");
 
diff --git a/hw/qxl.c b/hw/qxl.c
index 2bb36c660f..1906e84fab 100644
--- a/hw/qxl.c
+++ b/hw/qxl.c
@@ -357,7 +357,9 @@ static int interface_get_command(QXLInstance *sin, struct QXLCommandExt *ext)
             ret = true;
         }
         qemu_mutex_unlock(&qxl->ssd.lock);
-        qxl_log_command(qxl, "vga", ext);
+        if (ret) {
+            qxl_log_command(qxl, "vga", ext);
+        }
         return ret;
     case QXL_MODE_COMPAT:
     case QXL_MODE_NATIVE:
diff --git a/hw/scsi-bus.c b/hw/scsi-bus.c
index 837f24e212..ad6a730be0 100644
--- a/hw/scsi-bus.c
+++ b/hw/scsi-bus.c
@@ -413,7 +413,11 @@ int scsi_req_parse(SCSIRequest *req, uint8_t *buf)
     scsi_req_xfer_mode(req);
     req->cmd.lba = scsi_req_lba(req);
     trace_scsi_req_parsed(req->dev->id, req->lun, req->tag, buf[0],
-                          req->cmd.mode, req->cmd.xfer, req->cmd.lba);
+                          req->cmd.mode, req->cmd.xfer);
+    if (req->cmd.lba != -1) {
+        trace_scsi_req_parsed_lba(req->dev->id, req->lun, req->tag, buf[0],
+                              req->cmd.lba);
+    }
     return 0;
 }
 
diff --git a/hw/sga.c b/hw/sga.c
new file mode 100644
index 0000000000..7ef750adf6
--- /dev/null
+++ b/hw/sga.c
@@ -0,0 +1,56 @@
+/*
+ * QEMU dummy ISA device for loading sgabios option rom.
+ *
+ * Copyright (c) 2011 Glauber Costa, Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * sgabios code originally available at code.google.com/p/sgabios
+ *
+ */
+#include "pci.h"
+#include "pc.h"
+#include "loader.h"
+#include "sysemu.h"
+
+#define SGABIOS_FILENAME "sgabios.bin"
+
+typedef struct ISAGAState {
+    ISADevice dev;
+} ISASGAState;
+
+static int isa_cirrus_vga_initfn(ISADevice *dev)
+{
+    rom_add_vga(SGABIOS_FILENAME);
+    return 0;
+}
+
+static ISADeviceInfo sga_info = {
+    .qdev.name    = "sga",
+    .qdev.desc    = "Serial Graphics Adapter",
+    .qdev.size    = sizeof(ISASGAState),
+    .init         = isa_cirrus_vga_initfn,
+};
+
+static void sga_register(void)
+{
+      isa_qdev_register(&sga_info);
+}
+
+device_init(sga_register);
diff --git a/hw/vga-isa.c b/hw/vga-isa.c
index fde0d56fd3..245841f18b 100644
--- a/hw/vga-isa.c
+++ b/hw/vga-isa.c
@@ -77,7 +77,6 @@ static ISADeviceInfo vga_info = {
     .qdev.size     = sizeof(ISAVGAState),
     .qdev.vmsd     = &vmstate_vga_common,
     .qdev.reset     = vga_reset_isa,
-    .qdev.no_user  = 1,
     .init          = vga_initfn,
 };
 
diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c
index c19629d507..c018351095 100644
--- a/hw/virtio-pci.c
+++ b/hw/virtio-pci.c
@@ -26,6 +26,7 @@
 #include "loader.h"
 #include "kvm.h"
 #include "blockdev.h"
+#include "virtio-pci.h"
 
 /* from Linux's linux/virtio_pci.h */
 
@@ -95,27 +96,6 @@
  */
 #define wmb() do { } while (0)
 
-/* PCI bindings.  */
-
-typedef struct {
-    PCIDevice pci_dev;
-    VirtIODevice *vdev;
-    uint32_t flags;
-    uint32_t addr;
-    uint32_t class_code;
-    uint32_t nvectors;
-    BlockConf block;
-    NICConf nic;
-    uint32_t host_features;
-#ifdef CONFIG_LINUX
-    V9fsConf fsconf;
-#endif
-    virtio_serial_conf serial;
-    virtio_net_conf net;
-    bool ioeventfd_disabled;
-    bool ioeventfd_started;
-} VirtIOPCIProxy;
-
 /* virtio device */
 
 static void virtio_pci_notify(void *opaque, uint16_t vector)
@@ -669,7 +649,7 @@ static const VirtIOBindings virtio_pci_bindings = {
     .vmstate_change = virtio_pci_vmstate_change,
 };
 
-static void virtio_init_pci(VirtIOPCIProxy *proxy, VirtIODevice *vdev,
+void virtio_init_pci(VirtIOPCIProxy *proxy, VirtIODevice *vdev,
                             uint16_t vendor, uint16_t device,
                             uint16_t class_code, uint8_t pif)
 {
@@ -835,25 +815,6 @@ static int virtio_balloon_init_pci(PCIDevice *pci_dev)
     return 0;
 }
 
-#ifdef CONFIG_VIRTFS
-static int virtio_9p_init_pci(PCIDevice *pci_dev)
-{
-    VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
-    VirtIODevice *vdev;
-
-    vdev = virtio_9p_init(&pci_dev->qdev, &proxy->fsconf);
-    vdev->nvectors = proxy->nvectors;
-    virtio_init_pci(proxy, vdev,
-                    PCI_VENDOR_ID_REDHAT_QUMRANET,
-                    0x1009,
-                    0x2,
-                    0x00);
-    /* make the actual value visible */
-    proxy->nvectors = vdev->nvectors;
-    return 0;
-}
-#endif
-
 static PCIDeviceInfo virtio_info[] = {
     {
         .qdev.name = "virtio-blk-pci",
@@ -922,20 +883,6 @@ static PCIDeviceInfo virtio_info[] = {
         },
         .qdev.reset = virtio_pci_reset,
     },{
-#ifdef CONFIG_VIRTFS
-        .qdev.name = "virtio-9p-pci",
-        .qdev.alias = "virtio-9p",
-        .qdev.size = sizeof(VirtIOPCIProxy),
-        .init      = virtio_9p_init_pci,
-        .qdev.props = (Property[]) {
-            DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 2),
-            DEFINE_VIRTIO_COMMON_FEATURES(VirtIOPCIProxy, host_features),
-            DEFINE_PROP_STRING("mount_tag", VirtIOPCIProxy, fsconf.tag),
-            DEFINE_PROP_STRING("fsdev", VirtIOPCIProxy, fsconf.fsdev_id),
-            DEFINE_PROP_END_OF_LIST(),
-        },
-    }, {
-#endif
         /* end of list */
     }
 };
diff --git a/hw/virtio-pci.h b/hw/virtio-pci.h
new file mode 100644
index 0000000000..a4b5fd30e1
--- /dev/null
+++ b/hw/virtio-pci.h
@@ -0,0 +1,43 @@
+/*
+ * Virtio PCI Bindings
+ *
+ * Copyright IBM, Corp. 2007
+ * Copyright (c) 2009 CodeSourcery
+ *
+ * Authors:
+ *  Anthony Liguori   <aliguori@us.ibm.com>
+ *  Paul Brook        <paul@codesourcery.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.  See
+ * the COPYING file in the top-level directory.
+ */
+
+#ifndef QEMU_VIRTIO_PCI_H
+#define QEMU_VIRTIO_PCI_H
+
+#include "virtio-net.h"
+#include "virtio-serial.h"
+
+typedef struct {
+    PCIDevice pci_dev;
+    VirtIODevice *vdev;
+    uint32_t flags;
+    uint32_t addr;
+    uint32_t class_code;
+    uint32_t nvectors;
+    BlockConf block;
+    NICConf nic;
+    uint32_t host_features;
+#ifdef CONFIG_LINUX
+    V9fsConf fsconf;
+#endif
+    virtio_serial_conf serial;
+    virtio_net_conf net;
+    bool ioeventfd_disabled;
+    bool ioeventfd_started;
+} VirtIOPCIProxy;
+
+extern void virtio_init_pci(VirtIOPCIProxy *proxy, VirtIODevice *vdev,
+                            uint16_t vendor, uint16_t device,
+                            uint16_t class_code, uint8_t pif);
+#endif