rpms/qemu/devel qemu-exec-memory-notifiers.patch, NONE, 1.1 qemu-kvm-add-API-to-set-ioeventfd.patch, NONE, 1.1 qemu-kvm-add-vhost.h-header.patch, NONE, 1.1 qemu-kvm-irqfd-support.patch, NONE, 1.1 qemu-msix-add-mask-unmask-notifiers.patch, NONE, 1.1 qemu-net-add-API-to-disable-enable-polling.patch, NONE, 1.1 qemu-notifier-event-notifier-implementation.patch, NONE, 1.1 qemu-qdev-add-bit-property-type.patch, NONE, 1.1 qemu-qdev-fix-thinko-leading-to-guest-crashes.patch, NONE, 1.1 qemu-tap-add-API-to-retrieve-vhost-net-header.patch, NONE, 1.1 qemu-tap-add-interface-to-get-device-fd.patch, NONE, 1.1 qemu-tap-add-vhost-vhostfd-options.patch, NONE, 1.1 qemu-vhost-add-configure-check.patch, NONE, 1.1 qemu-vhost-vhost-net-support.patch, NONE, 1.1 qemu-virtio-add-APIs-for-queue-fields.patch, NONE, 1.1 qemu-virtio-add-features-as-qdev-properties.patch, NONE, 1.1 qemu-virtio-add-notifier-support.patch, NONE, 1.1 qemu-virtio-add-status-change-callback.patch, NONE, 1.1 qemu-virtio-avoid-crash-with-non-tap-backends.patch, NONE, 1.1 qemu-virtio-move-typedef-to-qemu-common.patch, NONE, 1.1 qemu-virtio-net-mac-property-is-mandatory.patch, NONE, 1.1 qemu-virtio-net-vhost-net-support.patch, NONE, 1.1 qemu-virtio-pci-fill-in-notifier-support.patch, NONE, 1.1 qemu-virtio-pci-irqfd-fix-nonkvm-build.patch, NONE, 1.1 qemu-virtio-pci-irqfd-support.patch, NONE, 1.1 qemu-virtio-rename-features-guest_features.patch, NONE, 1.1 qemu-virtio-serial-features-build-fix.patch, NONE, 1.1 qemu.spec, 1.156, 1.157

Justin M. Forbes jforbes at fedoraproject.org
Tue Feb 9 17:10:07 UTC 2010


Author: jforbes

Update of /cvs/pkgs/rpms/qemu/devel
In directory cvs1.fedora.phx.redhat.com:/tmp/cvs-serv19949

Modified Files:
	qemu.spec 
Added Files:
	qemu-exec-memory-notifiers.patch 
	qemu-kvm-add-API-to-set-ioeventfd.patch 
	qemu-kvm-add-vhost.h-header.patch qemu-kvm-irqfd-support.patch 
	qemu-msix-add-mask-unmask-notifiers.patch 
	qemu-net-add-API-to-disable-enable-polling.patch 
	qemu-notifier-event-notifier-implementation.patch 
	qemu-qdev-add-bit-property-type.patch 
	qemu-qdev-fix-thinko-leading-to-guest-crashes.patch 
	qemu-tap-add-API-to-retrieve-vhost-net-header.patch 
	qemu-tap-add-interface-to-get-device-fd.patch 
	qemu-tap-add-vhost-vhostfd-options.patch 
	qemu-vhost-add-configure-check.patch 
	qemu-vhost-vhost-net-support.patch 
	qemu-virtio-add-APIs-for-queue-fields.patch 
	qemu-virtio-add-features-as-qdev-properties.patch 
	qemu-virtio-add-notifier-support.patch 
	qemu-virtio-add-status-change-callback.patch 
	qemu-virtio-avoid-crash-with-non-tap-backends.patch 
	qemu-virtio-move-typedef-to-qemu-common.patch 
	qemu-virtio-net-mac-property-is-mandatory.patch 
	qemu-virtio-net-vhost-net-support.patch 
	qemu-virtio-pci-fill-in-notifier-support.patch 
	qemu-virtio-pci-irqfd-fix-nonkvm-build.patch 
	qemu-virtio-pci-irqfd-support.patch 
	qemu-virtio-rename-features-guest_features.patch 
	qemu-virtio-serial-features-build-fix.patch 
Log Message:
Add vhost net support.

qemu-exec-memory-notifiers.patch:
 cpu-common.h |   19 +++++++++
 exec.c       |  115 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
 2 files changed, 130 insertions(+), 4 deletions(-)

--- NEW FILE qemu-exec-memory-notifiers.patch ---
This adds notifiers for phys memory changes: a set of callbacks that
vhost can register and update kernel accordingly.  Down the road, kvm
code can be switched to use these as well, instead of calling kvm code
directly from exec.c as is done now.

Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
---
 cpu-common.h |   19 ++++++++++
 exec.c       |  114 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
 2 files changed, 130 insertions(+), 3 deletions(-)

diff --git a/cpu-common.h b/cpu-common.h
index 5e59564..326513d 100644
--- a/cpu-common.h
+++ b/cpu-common.h
@@ -8,6 +8,7 @@
 #endif
 
 #include "bswap.h"
+#include "qemu-queue.h"
 
 /* address in the RAM (different from a physical address) */
 typedef unsigned long ram_addr_t;
@@ -62,6 +63,24 @@ void cpu_physical_memory_unmap(void *buffer, target_phys_addr_t len,
 void *cpu_register_map_client(void *opaque, void (*callback)(void *opaque));
 void cpu_unregister_map_client(void *cookie);
 
+struct CPUPhysMemoryClient;
+typedef struct CPUPhysMemoryClient CPUPhysMemoryClient;
+struct CPUPhysMemoryClient {
+    void (*set_memory)(struct CPUPhysMemoryClient *client,
+                       target_phys_addr_t start_addr,
+                       ram_addr_t size,
+                       ram_addr_t phys_offset);
+    int (*sync_dirty_bitmap)(struct CPUPhysMemoryClient *client,
+                             target_phys_addr_t start_addr,
+                             target_phys_addr_t end_addr);
+    int (*migration_log)(struct CPUPhysMemoryClient *client,
+                         int enable);
+    QLIST_ENTRY(CPUPhysMemoryClient) list;
+};
+
+void cpu_register_phys_memory_client(CPUPhysMemoryClient *);
+void cpu_unregister_phys_memory_client(CPUPhysMemoryClient *);
+
 uint32_t ldub_phys(target_phys_addr_t addr);
 uint32_t lduw_phys(target_phys_addr_t addr);
 uint32_t ldl_phys(target_phys_addr_t addr);
diff --git a/exec.c b/exec.c
index 8f873ab..cbba15e 100644
--- a/exec.c
+++ b/exec.c
@@ -1640,6 +1640,101 @@ const CPULogItem cpu_log_items[] = {
     { 0, NULL, NULL },
 };
 
+#ifndef CONFIG_USER_ONLY
+static QLIST_HEAD(memory_client_list, CPUPhysMemoryClient) memory_client_list
+    = QLIST_HEAD_INITIALIZER(memory_client_list);
+
+static void cpu_notify_set_memory(target_phys_addr_t start_addr,
+				  ram_addr_t size,
+				  ram_addr_t phys_offset)
+{
+    CPUPhysMemoryClient *client;
+    QLIST_FOREACH(client, &memory_client_list, list) {
+        client->set_memory(client, start_addr, size, phys_offset);
+    }
+}
+
+static int cpu_notify_sync_dirty_bitmap(target_phys_addr_t start,
+					target_phys_addr_t end)
+{
+    CPUPhysMemoryClient *client;
+    QLIST_FOREACH(client, &memory_client_list, list) {
+        int r = client->sync_dirty_bitmap(client, start, end);
+        if (r < 0)
+            return r;
+    }
+    return 0;
+}
+
+static int cpu_notify_migration_log(int enable)
+{
+    CPUPhysMemoryClient *client;
+    QLIST_FOREACH(client, &memory_client_list, list) {
+        int r = client->migration_log(client, enable);
+        if (r < 0)
+            return r;
+    }
+    return 0;
+}
+
+static void phys_page_for_each_in_l1_map(PhysPageDesc **phys_map,
+                                         CPUPhysMemoryClient *client)
+{
+    PhysPageDesc *pd;
+    int l1, l2;
+
+    for (l1 = 0; l1 < L1_SIZE; ++l1) {
+        pd = phys_map[l1];
+        if (!pd) {
+            continue;
+        }
+        for (l2 = 0; l2 < L2_SIZE; ++l2) {
+            if (pd[l2].phys_offset == IO_MEM_UNASSIGNED) {
+                continue;
+            }
+            client->set_memory(client, pd[l2].region_offset,
+                               TARGET_PAGE_SIZE, pd[l2].phys_offset);
+        }
+    }
+}
+
+static void phys_page_for_each(CPUPhysMemoryClient *client)
+{
+#if TARGET_PHYS_ADDR_SPACE_BITS > 32
+
+#if TARGET_PHYS_ADDR_SPACE_BITS > (32 + L1_BITS)
+#error unsupported TARGET_PHYS_ADDR_SPACE_BITS
+#endif
+    void **phys_map = (void **)l1_phys_map;
+    int l1;
+    if (!l1_phys_map) {
+        return;
+    }
+    for (l1 = 0; l1 < L1_SIZE; ++l1) {
+        if (phys_map[l1]) {
+            phys_page_for_each_in_l1_map(phys_map[l1], client);
+        }
+    }
+#else
+    if (!l1_phys_map) {
+        return;
+    }
+    phys_page_for_each_in_l1_map(l1_phys_map, client);
+#endif
+}
+
+void cpu_register_phys_memory_client(CPUPhysMemoryClient *client)
+{
+    QLIST_INSERT_HEAD(&memory_client_list, client, list);
+    phys_page_for_each(client);
+}
+
+void cpu_unregister_phys_memory_client(CPUPhysMemoryClient *client)
+{
+    QLIST_REMOVE(client, list);
+}
+#endif
+
 static int cmp1(const char *s1, int n, const char *s2)
 {
     if (strlen(s2) != n)
@@ -1899,10 +1994,16 @@ void cpu_physical_memory_reset_dirty(ram_addr_t start, ram_addr_t end,
 
 int cpu_physical_memory_set_dirty_tracking(int enable)
 {
+    int ret = 0;
+    in_migration = enable;
     if (kvm_enabled()) {
-        return kvm_set_migration_log(enable);
+        ret = kvm_set_migration_log(enable);
     }
-    return 0;
+    if (ret < 0) {
+        return ret;
+    }
+    ret = cpu_notify_migration_log(!!enable);
+    return ret;
 }
 
 int cpu_physical_memory_get_dirty_tracking(void)
@@ -1915,8 +2016,13 @@ int cpu_physical_sync_dirty_bitmap(target_phys_addr_t start_addr,
 {
     int ret = 0;
 
-    if (kvm_enabled())
+    if (kvm_enabled()) {
         ret = kvm_physical_sync_dirty_bitmap(start_addr, end_addr);
+    }
+    if (ret < 0) {
+        return ret;
+    }
+    ret = cpu_notify_sync_dirty_bitmap(start_addr, end_addr);
     return ret;
 }
 
@@ -2331,6 +2437,8 @@ void cpu_register_physical_memory_offset(target_phys_addr_t start_addr,
     if (kvm_enabled())
         kvm_set_phys_mem(start_addr, size, phys_offset);
 
+    cpu_notify_set_memory(start_addr, size, phys_offset);
+
     if (phys_offset == IO_MEM_UNASSIGNED) {
         region_offset = start_addr;
     }
-- 
1.6.6.144.g5c3af

qemu-kvm-add-API-to-set-ioeventfd.patch:
 kvm-all.c |   20 ++++++++++++++++++++
 kvm.h     |   17 ++++++++++++++++-
 2 files changed, 36 insertions(+), 1 deletion(-)

--- NEW FILE qemu-kvm-add-API-to-set-ioeventfd.patch ---
This adds API to set ioeventfd to kvm,
as well as stubs for non-eventfd case,
making it possible for users to use this API
without ifdefs.

Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
---
 kvm-all.c |   20 ++++++++++++++++++++
 kvm.h     |   16 ++++++++++++++++
 2 files changed, 36 insertions(+), 0 deletions(-)

diff --git a/kvm-all.c b/kvm-all.c
index 0423fff..efdf40c 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -1102,4 +1102,24 @@ void kvm_remove_all_breakpoints(CPUState *current_env)
 }
 #endif /* !KVM_CAP_SET_GUEST_DEBUG */
 
+#ifdef KVM_IOEVENTFD
+int kvm_set_ioeventfd(uint16_t addr, uint16_t data, int fd, bool assigned)
+{
+    struct kvm_ioeventfd kick = {
+        .datamatch = data,
+        .addr = addr,
+        .len = 2,
+        .flags = KVM_IOEVENTFD_FLAG_DATAMATCH | KVM_IOEVENTFD_FLAG_PIO,
+        .fd = fd,
+    };
+    int r;
+    if (!assigned)
+        kick.flags |= KVM_IOEVENTFD_FLAG_DEASSIGN;
+    r = kvm_vm_ioctl(kvm_state, KVM_IOEVENTFD, &kick);
+    if (r < 0)
+        return r;
+    return 0;
+}
+#endif
+
 #include "qemu-kvm.c"
diff --git a/kvm.h b/kvm.h
index 9fa4e25..e98b5c8 100644
--- a/kvm.h
+++ b/kvm.h
@@ -14,6 +14,8 @@
 #ifndef QEMU_KVM_H
 #define QEMU_KVM_H
 
+#include <stdbool.h>
+#include <errno.h>
 #include "config.h"
 #include "qemu-queue.h"
 #include "qemu-kvm.h"
@@ -21,6 +23,10 @@
 #ifdef KVM_UPSTREAM
 
 #ifdef CONFIG_KVM
+#include <linux/kvm.h>
+#endif
+
+#ifdef CONFIG_KVM
 extern int kvm_allowed;
 
 #define kvm_enabled() (kvm_allowed)
@@ -151,4 +157,14 @@ static inline void cpu_synchronize_state(CPUState *env)
 
 #endif
 
+#if defined(KVM_IOEVENTFD) && defined(CONFIG_KVM)
+int kvm_set_ioeventfd(uint16_t addr, uint16_t data, int fd, bool assigned);
+#else
+static inline
+int kvm_set_ioeventfd(uint16_t data, uint16_t addr, int fd, bool assigned)
+{
+    return -ENOSYS;
+}
+#endif
+
 #endif
-- 
1.6.6.144.g5c3af

qemu-kvm-add-vhost.h-header.patch:
 vhost.h |  131 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 130 insertions(+), 1 deletion(-)

--- NEW FILE qemu-kvm-add-vhost.h-header.patch ---
This makes it possible to build vhost support
on systems which do not have this header.

Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
---
 kvm/include/linux/vhost.h |  130 +++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 130 insertions(+), 0 deletions(-)
 create mode 100644 kvm/include/linux/vhost.h

diff --git a/kvm/include/linux/vhost.h b/kvm/include/linux/vhost.h
new file mode 100644
index 0000000..165a484
--- /dev/null
+++ b/kvm/include/linux/vhost.h
@@ -0,0 +1,130 @@
+#ifndef _LINUX_VHOST_H
+#define _LINUX_VHOST_H
+/* Userspace interface for in-kernel virtio accelerators. */
+
+/* vhost is used to reduce the number of system calls involved in virtio.
+ *
+ * Existing virtio net code is used in the guest without modification.
+ *
+ * This header includes interface used by userspace hypervisor for
+ * device configuration.
+ */
+
+#include <linux/types.h>
+
+#include <linux/ioctl.h>
+#include <linux/virtio_config.h>
+#include <linux/virtio_ring.h>
+
+struct vhost_vring_state {
+	unsigned int index;
+	unsigned int num;
+};
+
+struct vhost_vring_file {
+	unsigned int index;
+	int fd; /* Pass -1 to unbind from file. */
+
+};
+
+struct vhost_vring_addr {
+	unsigned int index;
+	/* Option flags. */
+	unsigned int flags;
+	/* Flag values: */
+	/* Whether log address is valid. If set enables logging. */
+#define VHOST_VRING_F_LOG 0
+
+	/* Start of array of descriptors (virtually contiguous) */
+	__u64 desc_user_addr;
+	/* Used structure address. Must be 32 bit aligned */
+	__u64 used_user_addr;
+	/* Available structure address. Must be 16 bit aligned */
+	__u64 avail_user_addr;
+	/* Logging support. */
+	/* Log writes to used structure, at offset calculated from specified
+	 * address. Address must be 32 bit aligned. */
+	__u64 log_guest_addr;
+};
+
+struct vhost_memory_region {
+	__u64 guest_phys_addr;
+	__u64 memory_size; /* bytes */
+	__u64 userspace_addr;
+	__u64 flags_padding; /* No flags are currently specified. */
+};
+
+/* All region addresses and sizes must be 4K aligned. */
+#define VHOST_PAGE_SIZE 0x1000
+
+struct vhost_memory {
+	__u32 nregions;
+	__u32 padding;
+	struct vhost_memory_region regions[0];
+};
+
+/* ioctls */
+
+#define VHOST_VIRTIO 0xAF
+
+/* Features bitmask for forward compatibility.  Transport bits are used for
+ * vhost specific features. */
+#define VHOST_GET_FEATURES	_IOR(VHOST_VIRTIO, 0x00, __u64)
+#define VHOST_SET_FEATURES	_IOW(VHOST_VIRTIO, 0x00, __u64)
+
+/* Set current process as the (exclusive) owner of this file descriptor.  This
+ * must be called before any other vhost command.  Further calls to
+ * VHOST_OWNER_SET fail until VHOST_OWNER_RESET is called. */
+#define VHOST_SET_OWNER _IO(VHOST_VIRTIO, 0x01)
+/* Give up ownership, and reset the device to default values.
+ * Allows subsequent call to VHOST_OWNER_SET to succeed. */
+#define VHOST_RESET_OWNER _IO(VHOST_VIRTIO, 0x02)
+
+/* Set up/modify memory layout */
+#define VHOST_SET_MEM_TABLE	_IOW(VHOST_VIRTIO, 0x03, struct vhost_memory)
+
+/* Write logging setup. */
+/* Memory writes can optionally be logged by setting bit at an offset
+ * (calculated from the physical address) from specified log base.
+ * The bit is set using an atomic 32 bit operation. */
+/* Set base address for logging. */
+#define VHOST_SET_LOG_BASE _IOW(VHOST_VIRTIO, 0x04, __u64)
+/* Specify an eventfd file descriptor to signal on log write. */
+#define VHOST_SET_LOG_FD _IOW(VHOST_VIRTIO, 0x07, int)
+
+/* Ring setup. */
+/* Set number of descriptors in ring. This parameter can not
+ * be modified while ring is running (bound to a device). */
+#define VHOST_SET_VRING_NUM _IOW(VHOST_VIRTIO, 0x10, struct vhost_vring_state)
+/* Set addresses for the ring. */
+#define VHOST_SET_VRING_ADDR _IOW(VHOST_VIRTIO, 0x11, struct vhost_vring_addr)
+/* Base value where queue looks for available descriptors */
+#define VHOST_SET_VRING_BASE _IOW(VHOST_VIRTIO, 0x12, struct vhost_vring_state)
+/* Get accessor: reads index, writes value in num */
+#define VHOST_GET_VRING_BASE _IOWR(VHOST_VIRTIO, 0x12, struct vhost_vring_state)
+
+/* The following ioctls use eventfd file descriptors to signal and poll
+ * for events. */
+
+/* Set eventfd to poll for added buffers */
+#define VHOST_SET_VRING_KICK _IOW(VHOST_VIRTIO, 0x20, struct vhost_vring_file)
+/* Set eventfd to signal when buffers have beed used */
+#define VHOST_SET_VRING_CALL _IOW(VHOST_VIRTIO, 0x21, struct vhost_vring_file)
+/* Set eventfd to signal an error */
+#define VHOST_SET_VRING_ERR _IOW(VHOST_VIRTIO, 0x22, struct vhost_vring_file)
+
+/* VHOST_NET specific defines */
+
+/* Attach virtio net ring to a raw socket, or tap device.
+ * The socket must be already bound to an ethernet device, this device will be
+ * used for transmit.  Pass fd -1 to unbind from the socket and the transmit
+ * device.  This can be used to stop the ring (e.g. for migration). */
+#define VHOST_NET_SET_BACKEND _IOW(VHOST_VIRTIO, 0x30, struct vhost_vring_file)
+
+/* Feature bits */
+/* Log all write descriptors. Can be changed while device is active. */
+#define VHOST_F_LOG_ALL 26
+/* vhost-net should add virtio_net_hdr for RX, and strip for TX packets. */
+#define VHOST_NET_F_VIRTIO_NET_HDR 27
+
+#endif
-- 
1.6.6.144.g5c3af

qemu-kvm-irqfd-support.patch:
 kvm-all.c |   19 +++++++++++++++++++
 kvm.h     |   11 ++++++++++-
 2 files changed, 29 insertions(+), 1 deletion(-)

--- NEW FILE qemu-kvm-irqfd-support.patch ---
Add API to assign/deassign irqfd to kvm.
Add stub so that users do not have to use
ifdefs.

Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
---
 kvm-all.c |   19 +++++++++++++++++++
 kvm.h     |   10 ++++++++++
 2 files changed, 29 insertions(+), 0 deletions(-)

diff --git a/kvm-all.c b/kvm-all.c
index efdf40c..b3fdf29 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -1122,4 +1122,23 @@ int kvm_set_ioeventfd(uint16_t addr, uint16_t data, int fd, bool assigned)
 }
 #endif
 
+#if defined(KVM_IRQFD)
+int kvm_set_irqfd(int gsi, int fd, bool assigned)
+{
+    struct kvm_irqfd irqfd = {
+        .fd = fd,
+        .gsi = gsi,
+        .flags = assigned ? 0 : KVM_IRQFD_FLAG_DEASSIGN,
+    };
+    int r;
+    if (!kvm_irqchip_in_kernel())
+        return -ENOSYS;
+
+    r = kvm_vm_ioctl(kvm_state, KVM_IRQFD, &irqfd);
+    if (r < 0)
+        return r;
+    return 0;
+}
+#endif
+
 #include "qemu-kvm.c"
diff --git a/kvm.h b/kvm.h
index e98b5c8..ad8d122 100644
--- a/kvm.h
+++ b/kvm.h
@@ -167,4 +167,14 @@ int kvm_set_ioeventfd(uint16_t data, uint16_t addr, int fd, bool assigned)
 }
 #endif
 
+#if defined(KVM_IRQFD) && defined(CONFIG_KVM)
+int kvm_set_irqfd(int gsi, int fd, bool assigned);
+#else
+static inline
+int kvm_set_irqfd(int gsi, int fd, bool assigned)
+{
+    return -ENOSYS;
+}
+#endif
+
 #endif
-- 
1.6.6.144.g5c3af

qemu-msix-add-mask-unmask-notifiers.patch:
 msix.c |   36 +++++++++++++++++++++++++++++++++++-
 msix.h |    1 +
 pci.h  |    7 ++++++-
 3 files changed, 42 insertions(+), 2 deletions(-)

--- NEW FILE qemu-msix-add-mask-unmask-notifiers.patch ---
Support per-vector callbacks for msix mask/unmask.
Will be used for vhost net.

Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
---
 hw/msix.c |   36 +++++++++++++++++++++++++++++++++++-
 hw/msix.h |    1 +
 hw/pci.h  |    6 ++++++
 3 files changed, 42 insertions(+), 1 deletions(-)

diff --git a/hw/msix.c b/hw/msix.c
index d117bcf..3fcf3a1 100644
--- a/hw/msix.c
+++ b/hw/msix.c
@@ -318,6 +318,13 @@ static void msix_mmio_writel(void *opaque, target_phys_addr_t addr,
     if (kvm_enabled() && kvm_irqchip_in_kernel()) {
         kvm_msix_update(dev, vector, was_masked, msix_is_masked(dev, vector));
     }
+    if (was_masked != msix_is_masked(dev, vector) &&
+        dev->msix_mask_notifier && dev->msix_mask_notifier_opaque[vector]) {
+        int r = dev->msix_mask_notifier(dev, vector,
+					dev->msix_mask_notifier_opaque[vector],
+					msix_is_masked(dev, vector));
+        assert(r >= 0);
+    }
     msix_handle_mask_update(dev, vector);
 }
 
@@ -356,10 +363,18 @@ void msix_mmio_map(PCIDevice *d, int region_num,
 
 static void msix_mask_all(struct PCIDevice *dev, unsigned nentries)
 {
-    int vector;
+    int vector, r;
     for (vector = 0; vector < nentries; ++vector) {
         unsigned offset = vector * MSIX_ENTRY_SIZE + MSIX_VECTOR_CTRL;
+        int was_masked = msix_is_masked(dev, vector);
         dev->msix_table_page[offset] |= MSIX_VECTOR_MASK;
+        if (was_masked != msix_is_masked(dev, vector) &&
+            dev->msix_mask_notifier && dev->msix_mask_notifier_opaque[vector]) {
+            r = dev->msix_mask_notifier(dev, vector,
+                                        dev->msix_mask_notifier_opaque[vector],
+                                        msix_is_masked(dev, vector));
+            assert(r >= 0);
+        }
     }
 }
 
@@ -382,6 +397,9 @@ int msix_init(struct PCIDevice *dev, unsigned short nentries,
                                             sizeof *dev->msix_irq_entries);
     }
 #endif
+    dev->msix_mask_notifier_opaque =
+        qemu_mallocz(nentries * sizeof *dev->msix_mask_notifier_opaque);
+    dev->msix_mask_notifier = NULL;
     dev->msix_entry_used = qemu_mallocz(MSIX_MAX_ENTRIES *
                                         sizeof *dev->msix_entry_used);
 
@@ -444,6 +462,8 @@ int msix_uninit(PCIDevice *dev)
     dev->msix_entry_used = NULL;
     qemu_free(dev->msix_irq_entries);
     dev->msix_irq_entries = NULL;
+    qemu_free(dev->msix_mask_notifier_opaque);
+    dev->msix_mask_notifier_opaque = NULL;
     dev->cap_present &= ~QEMU_PCI_CAP_MSIX;
     return 0;
 }
@@ -587,3 +607,17 @@ void msix_unuse_all_vectors(PCIDevice *dev)
         return;
     msix_free_irq_entries(dev);
 }
+
+int msix_set_mask_notifier(PCIDevice *dev, unsigned vector, void *opaque)
+{
+    int r = 0;
+    if (vector >= dev->msix_entries_nr || !dev->msix_entry_used[vector])
+        return 0;
+
+    if (dev->msix_mask_notifier)
+        r = dev->msix_mask_notifier(dev, vector, opaque,
+                                    msix_is_masked(dev, vector));
+    if (r >= 0)
+        dev->msix_mask_notifier_opaque[vector] = opaque;
+    return r;
+}
diff --git a/hw/msix.h b/hw/msix.h
index a9f7993..f167231 100644
--- a/hw/msix.h
+++ b/hw/msix.h
@@ -33,4 +33,5 @@ void msix_reset(PCIDevice *dev);
 
 extern int msix_supported;
 
+int msix_set_mask_notifier(PCIDevice *dev, unsigned vector, void *opaque);
 #endif
diff --git a/hw/pci.h b/hw/pci.h
index a225a6a..bf722ca 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -217,6 +217,9 @@ enum {
 #define PCI_CAPABILITY_CONFIG_MSI_LENGTH 0x10
 #define PCI_CAPABILITY_CONFIG_MSIX_LENGTH 0x10
 
+typedef int (*msix_mask_notifier_func)(PCIDevice *, unsigned vector,
+				       void *opaque, int masked);
+
 struct PCIDevice {
     DeviceState qdev;
     /* PCI config space */
@@ -282,6 +285,9 @@ struct PCIDevice {
 
     struct kvm_irq_routing_entry *msix_irq_entries;
 
+    void **msix_mask_notifier_opaque;
+    msix_mask_notifier_func msix_mask_notifier;
+
     /* Device capability configuration space */
     struct {
         int supported;
-- 
1.6.6.144.g5c3af

qemu-net-add-API-to-disable-enable-polling.patch:
 net.h     |    3 +++
 net/tap.c |    9 ++++++++-
 2 files changed, 11 insertions(+), 1 deletion(-)

--- NEW FILE qemu-net-add-API-to-disable-enable-polling.patch ---
When vhost is bound to a backend device, we need to stop polling it when
vhost is started, and restart polling when vhost is stopped.
Add an API for that for use by vhost, and implement in tap backend.

Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
(cherry picked from commit ceb696159d569db5b2a7659ce38752398c236742)
---
 net.h     |    3 +++
 net/tap.c |    8 ++++++++
 2 files changed, 11 insertions(+), 0 deletions(-)

diff --git a/net.h b/net.h
index 4971fcb..116bb80 100644
--- a/net.h
+++ b/net.h
@@ -1,6 +1,7 @@
 #ifndef QEMU_NET_H
 #define QEMU_NET_H
 
+#include <stdbool.h>
 #include "qemu-queue.h"
 #include "qemu-common.h"
 #include "qdict.h"
@@ -36,6 +37,7 @@ typedef enum {
     NET_CLIENT_TYPE_DUMP
 } net_client_type;
 
+typedef void (NetPoll)(VLANClientState *, bool enable);
 typedef int (NetCanReceive)(VLANClientState *);
 typedef ssize_t (NetReceive)(VLANClientState *, const uint8_t *, size_t);
 typedef ssize_t (NetReceiveIOV)(VLANClientState *, const struct iovec *, int);
@@ -51,6 +53,7 @@ typedef struct NetClientInfo {
     NetCanReceive *can_receive;
     NetCleanup *cleanup;
     LinkStatusChanged *link_status_changed;
+    NetPoll *poll;
 } NetClientInfo;
 
 struct VLANClientState {
diff --git a/net/tap.c b/net/tap.c
index 0d8b424..d3492de 100644
--- a/net/tap.c
+++ b/net/tap.c
@@ -262,6 +262,13 @@ static void tap_cleanup(VLANClientState *nc)
     close(s->fd);
 }
 
+static void tap_poll(VLANClientState *nc, bool enable)
+{
+    TAPState *s = DO_UPCAST(TAPState, nc, nc);
+    tap_read_poll(s, enable);
+    tap_write_poll(s, enable);
+}
+
 /* fd support */
 
 static NetClientInfo net_tap_info = {
@@ -270,6 +277,7 @@ static NetClientInfo net_tap_info = {
     .receive = tap_receive,
     .receive_raw = tap_receive_raw,
     .receive_iov = tap_receive_iov,
+    .poll = tap_poll,
     .cleanup = tap_cleanup,
 };
 
-- 
1.6.6.144.g5c3af

qemu-notifier-event-notifier-implementation.patch:
 Makefile.target |    1 +
 hw/notifier.c   |   50 ++++++++++++++++++++++++++++++++++++++++++++++++++
 hw/notifier.h   |   16 ++++++++++++++++
 qemu-common.h   |    2 +-
 4 files changed, 68 insertions(+), 1 deletion(-)

--- NEW FILE qemu-notifier-event-notifier-implementation.patch ---
event notifiers are slightly generalized eventfd descriptors. Current
implementation depends on eventfd because vhost is the only user, and
vhost depends on eventfd anyway, but a stub is provided for non-eventfd
case.

We'll be able to further generalize this when another user comes along
and we see how to best do this.

Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
---
 Makefile.target |    1 +
 hw/notifier.c   |   50 ++++++++++++++++++++++++++++++++++++++++++++++++++
 hw/notifier.h   |   16 ++++++++++++++++
 qemu-common.h   |    1 +
 4 files changed, 68 insertions(+), 0 deletions(-)
 create mode 100644 hw/notifier.c
 create mode 100644 hw/notifier.h

diff --git a/Makefile.target b/Makefile.target
index 6037fed..0c844a9 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -167,6 +167,7 @@ obj-y = vl.o async.o monitor.o pci.o pci_host.o pcie_host.o machine.o gdbstub.o
 # virtio has to be here due to weird dependency between PCI and virtio-net.
 # need to fix this properly
 obj-y += virtio-blk.o virtio-balloon.o virtio-net.o virtio-pci.o virtio-serial-bus.o
+obj-y += notifier.o
 obj-$(CONFIG_KVM) += kvm.o kvm-all.o
 # MSI-X depends on kvm for interrupt injection,
 # so moved it from Makefile.hw to Makefile.target for now
diff --git a/hw/notifier.c b/hw/notifier.c
new file mode 100644
index 0000000..dff38de
--- /dev/null
+++ b/hw/notifier.c
@@ -0,0 +1,50 @@
+#include "hw.h"
+#include "notifier.h"
+#ifdef CONFIG_EVENTFD
+#include <sys/eventfd.h>
+#endif
+
+int event_notifier_init(EventNotifier *e, int active)
+{
+#ifdef CONFIG_EVENTFD
+	int fd = eventfd(!!active, EFD_NONBLOCK | EFD_CLOEXEC);
+	if (fd < 0)
+		return -errno;
+	e->fd = fd;
+	return 0;
+#else
+	return -ENOSYS;
+#endif
+}
+
+void event_notifier_cleanup(EventNotifier *e)
+{
+	close(e->fd);
+}
+
+int event_notifier_get_fd(EventNotifier *e)
+{
+	return e->fd;
+}
+
+int event_notifier_test_and_clear(EventNotifier *e)
+{
+	uint64_t value;
+	int r = read(e->fd, &value, sizeof value);
+	return r == sizeof value;
+}
+
+int event_notifier_test(EventNotifier *e)
+{
+	uint64_t value;
+	int r = read(e->fd, &value, sizeof value);
+	if (r == sizeof value) {
+		/* restore previous value. */
+		int s = write(e->fd, &value, sizeof value);
+		/* never blocks because we use EFD_SEMAPHORE.
+		 * If we didn't we'd get EAGAIN on overflow
+		 * and we'd have to write code to ignore it. */
+		assert(s == sizeof value);
+	}
+	return r == sizeof value;
+}
diff --git a/hw/notifier.h b/hw/notifier.h
new file mode 100644
index 0000000..24117ea
--- /dev/null
+++ b/hw/notifier.h
@@ -0,0 +1,16 @@
+#ifndef QEMU_EVENT_NOTIFIER_H
+#define QEMU_EVENT_NOTIFIER_H
+
+#include "qemu-common.h"
+
+struct EventNotifier {
+	int fd;
+};
+
+int event_notifier_init(EventNotifier *, int active);
+void event_notifier_cleanup(EventNotifier *);
+int event_notifier_get_fd(EventNotifier *);
+int event_notifier_test_and_clear(EventNotifier *);
+int event_notifier_test(EventNotifier *);
+
+#endif
diff --git a/qemu-common.h b/qemu-common.h
index 5fbe0f9..cdead98 100644
--- a/qemu-common.h
+++ b/qemu-common.h
@@ -217,6 +217,7 @@ typedef struct uWireSlave uWireSlave;
 typedef struct I2SCodec I2SCodec;
 typedef struct DeviceState DeviceState;
 typedef struct SSIBus SSIBus;
+typedef struct EventNotifier EventNotifier;
 
 /* CPU save/load.  */
 void cpu_save(QEMUFile *f, void *opaque);
-- 
1.6.6.144.g5c3af

qemu-qdev-add-bit-property-type.patch:
 qdev-properties.c |   62 +++++++++++++++++++++++++++++++++++++++++++++++-------
 qdev.h            |   12 +++++++++-
 2 files changed, 66 insertions(+), 8 deletions(-)

--- NEW FILE qemu-qdev-add-bit-property-type.patch ---
This adds "bit" property type, which is a boolean stored in a 32 bit
integer field, with legal values on and off.  Will be used by virtio for
feature bits.

Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
Acked-by: Gerd Hoffmann <kraxel at redhat.com>
Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
(cherry picked from commit d2364ee424ebf9180afaf21128a71da55321ad00)
---
 hw/qdev-properties.c |   62 ++++++++++++++++++++++++++++++++++++++++++++-----
 hw/qdev.h            |   11 +++++++++
 2 files changed, 66 insertions(+), 7 deletions(-)

diff --git a/hw/qdev-properties.c b/hw/qdev-properties.c
index 217ddc0..9e123ae 100644
--- a/hw/qdev-properties.c
+++ b/hw/qdev-properties.c
@@ -9,6 +9,59 @@ void *qdev_get_prop_ptr(DeviceState *dev, Property *prop)
     return ptr;
 }
 
+static uint32_t qdev_get_prop_mask(Property *prop)
+{
+    assert(prop->info->type == PROP_TYPE_BIT);
+    return 0x1 << prop->bitnr;
+}
+
+static void bit_prop_set(DeviceState *dev, Property *props, bool val)
+{
+    uint32_t *p = qdev_get_prop_ptr(dev, props);
+    uint32_t mask = qdev_get_prop_mask(props);
+    if (val)
+        *p |= ~mask;
+    else
+        *p &= ~mask;
+}
+
+static void qdev_prop_cpy(DeviceState *dev, Property *props, void *src)
+{
+    if (props->info->type == PROP_TYPE_BIT) {
+        bool *defval = src;
+        bit_prop_set(dev, props, *defval);
+    } else {
+        char *dst = qdev_get_prop_ptr(dev, props);
+        memcpy(dst, src, props->info->size);
+    }
+}
+
+/* Bit */
+static int parse_bit(DeviceState *dev, Property *prop, const char *str)
+{
+    if (!strncasecmp(str, "on", 2))
+        bit_prop_set(dev, prop, true);
+    else if (!strncasecmp(str, "off", 3))
+        bit_prop_set(dev, prop, false);
+    else
+        return -1;
+    return 0;
+}
+
+static int print_bit(DeviceState *dev, Property *prop, char *dest, size_t len)
+{
+    uint8_t *p = qdev_get_prop_ptr(dev, prop);
+    return snprintf(dest, len, (*p & qdev_get_prop_mask(prop)) ? "on" : "off");
+}
+
+PropertyInfo qdev_prop_bit = {
+    .name  = "on/off",
+    .type  = PROP_TYPE_BIT,
+    .size  = sizeof(uint32_t),
+    .parse = parse_bit,
+    .print = print_bit,
+};
+
 /* --- 8bit integer --- */
 
 static int parse_uint8(DeviceState *dev, Property *prop, const char *str)
@@ -511,7 +564,6 @@ int qdev_prop_parse(DeviceState *dev, const char *name, const char *value)
 void qdev_prop_set(DeviceState *dev, const char *name, void *src, enum PropertyType type)
 {
     Property *prop;
-    void *dst;
 
     prop = qdev_prop_find(dev, name);
     if (!prop) {
@@ -524,8 +576,7 @@ void qdev_prop_set(DeviceState *dev, const char *name, void *src, enum PropertyT
                 __FUNCTION__, dev->info->name, name);
         abort();
     }
-    dst = qdev_get_prop_ptr(dev, prop);
-    memcpy(dst, src, prop->info->size);
+    qdev_prop_cpy(dev, prop, src);
 }
 
 void qdev_prop_set_uint8(DeviceState *dev, const char *name, uint8_t value)
@@ -585,14 +636,11 @@ void qdev_prop_set_ptr(DeviceState *dev, const char *name, void *value)
 
 void qdev_prop_set_defaults(DeviceState *dev, Property *props)
 {
-    char *dst;
-
     if (!props)
         return;
     while (props->name) {
         if (props->defval) {
-            dst = qdev_get_prop_ptr(dev, props);
-            memcpy(dst, props->defval, props->info->size);
+            qdev_prop_cpy(dev, props, props->defval);
         }
         props++;
     }
diff --git a/hw/qdev.h b/hw/qdev.h
index bbcdba1..07b9603 100644
--- a/hw/qdev.h
+++ b/hw/qdev.h
@@ -64,6 +64,7 @@ struct Property {
     const char   *name;
     PropertyInfo *info;
     int          offset;
+    int          bitnr;
     void         *defval;
 };
 
@@ -82,6 +83,7 @@ enum PropertyType {
     PROP_TYPE_NETDEV,
     PROP_TYPE_VLAN,
     PROP_TYPE_PTR,
+    PROP_TYPE_BIT,
 };
 
 struct PropertyInfo {
@@ -173,6 +175,7 @@ void do_device_del(Monitor *mon, const QDict *qdict);
 
 /*** qdev-properties.c ***/
 
+extern PropertyInfo qdev_prop_bit;
 extern PropertyInfo qdev_prop_uint8;
 extern PropertyInfo qdev_prop_uint16;
 extern PropertyInfo qdev_prop_uint32;
@@ -202,6 +205,14 @@ extern PropertyInfo qdev_prop_pci_devfn;
             + type_check(_type,typeof_field(_state, _field)),           \
         .defval    = (_type[]) { _defval },                             \
         }
+#define DEFINE_PROP_BIT(_name, _state, _field, _bit, _defval) {  \
+        .name      = (_name),                                    \
+        .info      = &(qdev_prop_bit),                           \
+        .bitnr    = (_bit),                                      \
+        .offset    = offsetof(_state, _field)                    \
+            + type_check(uint32_t,typeof_field(_state, _field)), \
+        .defval    = (bool[]) { (_defval) },                     \
+        }
 
 #define DEFINE_PROP_UINT8(_n, _s, _f, _d)                       \
     DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_uint8, uint8_t)
-- 
1.6.6.144.g5c3af

qemu-qdev-fix-thinko-leading-to-guest-crashes.patch:
 qdev-properties.c |    3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

--- NEW FILE qemu-qdev-fix-thinko-leading-to-guest-crashes.patch ---
Without this fix, guest crashes with drive=virtio.

Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
(cherry picked from commit dbd483242c2e6dfaacb9fd3d20c333bbdad87243)
---
 hw/qdev-properties.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/hw/qdev-properties.c b/hw/qdev-properties.c
index 9e123ae..277ff9e 100644
--- a/hw/qdev-properties.c
+++ b/hw/qdev-properties.c
@@ -20,7 +20,7 @@ static void bit_prop_set(DeviceState *dev, Property *props, bool val)
     uint32_t *p = qdev_get_prop_ptr(dev, props);
     uint32_t mask = qdev_get_prop_mask(props);
     if (val)
-        *p |= ~mask;
+        *p |= mask;
     else
         *p &= ~mask;
 }
-- 
1.6.6.144.g5c3af

qemu-tap-add-API-to-retrieve-vhost-net-header.patch:
 tap.c |    7 +++++++
 tap.h |    4 +++-
 2 files changed, 10 insertions(+), 1 deletion(-)

--- NEW FILE qemu-tap-add-API-to-retrieve-vhost-net-header.patch ---
will be used by virtio-net for vhost net support

Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
---
 net/tap.c |    7 +++++++
 net/tap.h |    3 +++
 2 files changed, 10 insertions(+), 0 deletions(-)

diff --git a/net/tap.c b/net/tap.c
index d9f2e41..166cf05 100644
--- a/net/tap.c
+++ b/net/tap.c
@@ -491,3 +491,10 @@ int net_init_tap(QemuOpts *opts, Monitor *mon, const char *name, VLANState *vlan
 
     return 0;
 }
+
+struct vhost_net *tap_get_vhost_net(VLANClientState *nc)
+{
+    TAPState *s = DO_UPCAST(TAPState, nc, nc);
+    assert(nc->info->type == NET_CLIENT_TYPE_TAP);
+    return s->vhost_net;
+}
diff --git a/net/tap.h b/net/tap.h
index a244b28..b8cec83 100644
--- a/net/tap.h
+++ b/net/tap.h
@@ -50,4 +50,7 @@ void tap_fd_set_offload(int fd, int csum, int tso4, int tso6, int ecn, int ufo);
 
 int tap_get_fd(VLANClientState *vc);
 
+struct vhost_net;
+struct vhost_net *tap_get_vhost_net(VLANClientState *vc);
+
 #endif /* QEMU_NET_TAP_H */
-- 
1.6.6.144.g5c3af

qemu-tap-add-interface-to-get-device-fd.patch:
 tap.c |    7 +++++++
 tap.h |    3 ++-
 2 files changed, 9 insertions(+), 1 deletion(-)

--- NEW FILE qemu-tap-add-interface-to-get-device-fd.patch ---
Will be used by vhost to attach/detach to backend.

Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
---
 net/tap.c |    7 +++++++
 net/tap.h |    2 ++
 2 files changed, 9 insertions(+), 0 deletions(-)

diff --git a/net/tap.c b/net/tap.c
index d3492de..7e9ca79 100644
--- a/net/tap.c
+++ b/net/tap.c
@@ -269,6 +269,13 @@ static void tap_poll(VLANClientState *nc, bool enable)
     tap_write_poll(s, enable);
 }
 
+int tap_get_fd(VLANClientState *nc)
+{
+    TAPState *s = DO_UPCAST(TAPState, nc, nc);
+    assert(nc->info->type == NET_CLIENT_TYPE_TAP);
+    return s->fd;
+}
+
 /* fd support */
 
 static NetClientInfo net_tap_info = {
diff --git a/net/tap.h b/net/tap.h
index 538a562..a244b28 100644
--- a/net/tap.h
+++ b/net/tap.h
@@ -48,4 +48,6 @@ int tap_probe_vnet_hdr(int fd);
 int tap_probe_has_ufo(int fd);
 void tap_fd_set_offload(int fd, int csum, int tso4, int tso6, int ecn, int ufo);
 
+int tap_get_fd(VLANClientState *vc);
+
 #endif /* QEMU_NET_TAP_H */
-- 
1.6.6.144.g5c3af

qemu-tap-add-vhost-vhostfd-options.patch:
 net.c           |    8 ++++++++
 net/tap.c       |   29 +++++++++++++++++++++++++++++
 qemu-options.hx |    5 +++--
 3 files changed, 40 insertions(+), 2 deletions(-)

--- NEW FILE qemu-tap-add-vhost-vhostfd-options.patch ---
Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
---
 net.c           |    8 ++++++++
 net/tap.c       |   29 +++++++++++++++++++++++++++++
 qemu-options.hx |    4 +++-
 3 files changed, 40 insertions(+), 1 deletions(-)

diff --git a/net.c b/net.c
index 6ef93e6..b942d03 100644
--- a/net.c
+++ b/net.c
@@ -976,6 +976,14 @@ static struct {
                 .name = "vnet_hdr",
                 .type = QEMU_OPT_BOOL,
                 .help = "enable the IFF_VNET_HDR flag on the tap interface"
+            }, {
+                .name = "vhost",
+                .type = QEMU_OPT_BOOL,
+                .help = "enable vhost-net network accelerator",
+            }, {
+                .name = "vhostfd",
+                .type = QEMU_OPT_STRING,
+                .help = "file descriptor of an already opened vhost net device",
             },
 #endif /* _WIN32 */
             { /* end of list */ }
diff --git a/net/tap.c b/net/tap.c
index 7e9ca79..d9f2e41 100644
--- a/net/tap.c
+++ b/net/tap.c
@@ -41,6 +41,8 @@
 
 #include "net/tap-linux.h"
 
+#include "hw/vhost_net.h"
+
 /* Maximum GSO packet size (64k) plus plenty of room for
  * the ethernet and virtio_net headers
  */
@@ -57,6 +59,7 @@ typedef struct TAPState {
     unsigned int has_vnet_hdr : 1;
     unsigned int using_vnet_hdr : 1;
     unsigned int has_ufo: 1;
+    struct vhost_net *vhost_net;
 } TAPState;
 
 static int launch_script(const char *setup_script, const char *ifname, int fd);
@@ -252,6 +255,10 @@ static void tap_cleanup(VLANClientState *nc)
 {
     TAPState *s = DO_UPCAST(TAPState, nc, nc);
 
+    if (s->vhost_net) {
+        vhost_net_cleanup(s->vhost_net);
+    }
+
     qemu_purge_queued_packets(nc);
 
     if (s->down_script[0])
@@ -307,6 +314,7 @@ static TAPState *net_tap_fd_init(VLANState *vlan,
     s->has_ufo = tap_probe_has_ufo(s->fd);
     tap_set_offload(&s->nc, 0, 0, 0, 0, 0);
     tap_read_poll(s, 1);
+    s->vhost_net = NULL;
     return s;
 }
 
@@ -456,6 +464,27 @@ int net_init_tap(QemuOpts *opts, Monitor *mon, const char *name, VLANState *vlan
         }
     }
 
+    if (qemu_opt_get_bool(opts, "vhost", 0)) {
+        int vhostfd, r;
+        if (qemu_opt_get(opts, "vhostfd")) {
+            r = net_handle_fd_param(mon, qemu_opt_get(opts, "vhostfd"));
+            if (r == -1) {
+                return -1;
+            }
+            vhostfd = r;
+        } else {
+            vhostfd = -1;
+        }
+        s->vhost_net = vhost_net_init(&s->nc, vhostfd);
+        if (!s->vhost_net) {
+            qemu_error("vhost-net requested but could not be initialized\n");
+            return -1;
+        }
+    } else if (qemu_opt_get(opts, "vhostfd")) {
+        qemu_error("vhostfd= is not valid without vhost\n");
+        return -1;
+    }
+
     if (vlan) {
         vlan->nb_host_devs++;
     }
diff --git a/qemu-options.hx b/qemu-options.hx
index ca73ba5..2b3d9b8 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -814,7 +814,7 @@ DEF("net", HAS_ARG, QEMU_OPTION_net,
     "-net tap[,vlan=n][,name=str],ifname=name\n"
     "                connect the host TAP network interface to VLAN 'n'\n"
 #else
-    "-net tap[,vlan=n][,name=str][,fd=h][,ifname=name][,script=file][,downscript=dfile][,sndbuf=nbytes][,vnet_hdr=on|off]\n"
+    "-net tap[,vlan=n][,name=str][,fd=h][,ifname=name][,script=file][,downscript=dfile][,sndbuf=nbytes][,vnet_hdr=on|off][,vhost=on|off][,vhostfd=h]\n"
     "                connect the host TAP network interface to VLAN 'n' and use the\n"
     "                network scripts 'file' (default=%s)\n"
     "                and 'dfile' (default=%s);\n"
@@ -824,6 +824,8 @@ DEF("net", HAS_ARG, QEMU_OPTION_net,
     "                default of 'sndbuf=1048576' can be disabled using 'sndbuf=0'\n"
     "                use vnet_hdr=off to avoid enabling the IFF_VNET_HDR tap flag; use\n"
     "                vnet_hdr=on to make the lack of IFF_VNET_HDR support an error condition\n"
+    "                use vhost=on to enable experimental in kernel accelerator\n"
+    "                use 'vhostfd=h' to connect to an already opened vhost net device\n"
 #endif
     "-net socket[,vlan=n][,name=str][,fd=h][,listen=[host]:port][,connect=host:port]\n"
     "                connect the vlan 'n' to another VLAN using a socket connection\n"
-- 
1.6.6.144.g5c3af

qemu-vhost-add-configure-check.patch:
 Makefile.target |    3 ++-
 configure       |   21 +++++++++++++++++++++
 hw/vhost_net.c  |   34 +++++++++++++++++++++++++++++++++-
 3 files changed, 56 insertions(+), 2 deletions(-)

--- NEW FILE qemu-vhost-add-configure-check.patch ---
Teach configure to check for vhost.h
and disable vhost_net if not present.

Signed-off-by: Michael S. Tsirkin <mst at redhat.com>'

---

diff --git a/Makefile.target b/Makefile.target
index 2ebd30c..38783da 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -168,7 +168,8 @@ obj-y = vl.o async.o monitor.o pci.o pci_host.o pcie_host.o machine.o gdbstub.o
 # need to fix this properly
 obj-y += virtio-blk.o virtio-balloon.o virtio-net.o virtio-pci.o virtio-serial-bus.o
 obj-y += notifier.o
-obj-y += vhost_net.o vhost.o
+obj-y += vhost_net.o
+obj-$(CONFIG_VHOST_NET) += vhost.o
 obj-$(CONFIG_KVM) += kvm.o kvm-all.o
 # MSI-X depends on kvm for interrupt injection,
 # so moved it from Makefile.hw to Makefile.target for now
diff --git a/configure b/configure
index 88ba002..4994506 100755
--- a/configure
+++ b/configure
@@ -1510,6 +1510,23 @@ EOF
 fi
 
 ##########################################
+# test for vhost net
+
+if test "$kvm" != "no"; then
+	cat > $TMPC <<EOF
+#include <linux/vhost.h>
+int main(void) { return 0; }
+EOF
+	if compile_prog "$kvm_cflags" "" ; then
+	vhost_net=yes
+	else
+	vhost_net=no
+	fi
+else
+	vhost_net=no
+fi
+
+##########################################
 # libpci probe for kvm_cap_device_assignment
 if test $kvm_cap_device_assignment = "yes" ; then
   cat > $TMPC << EOF
@@ -2058,6 +2075,7 @@ echo "fdt support       $fdt"
 echo "preadv support    $preadv"
 echo "fdatasync         $fdatasync"
 echo "uuid support      $uuid"
+echo "vhost-net support $vhost_net"
 
 if test $sdl_too_old = "yes"; then
 echo "-> Your SDL version is too old - please upgrade to have SDL support"
@@ -2593,6 +2611,9 @@ case "$target_arch2" in
       if test $kvm_cap_device_assignment = "yes" ; then
         echo "CONFIG_KVM_DEVICE_ASSIGNMENT=y" >> $config_target_mak
       fi
+      if test $vhost_net = "yes" ; then
+        echo "CONFIG_VHOST_NET=y" >> $config_target_mak
+      fi
     fi
 esac
 echo "TARGET_PHYS_ADDR_BITS=$target_phys_bits" >> $config_target_mak
diff --git a/hw/vhost_net.c b/hw/vhost_net.c
index c89ff40..cab9a0a 100644
--- a/hw/vhost_net.c
+++ b/hw/vhost_net.c
@@ -16,9 +16,13 @@
 #include "net/tap.h"
 
 #include "virtio-net.h"
-#include "vhost.h"
 #include "vhost_net.h"
 
+#include "config.h"
+
+#ifdef CONFIG_VHOST_NET
+#include "vhost.h"
+
 struct vhost_net {
 	struct vhost_dev dev;
 	struct vhost_virtqueue vqs[2];
@@ -145,3 +149,31 @@ void vhost_net_cleanup(struct vhost_net *net)
 	qemu_free(net);
 }
 /* TODO: log */
+#else
+struct vhost_net *vhost_net_init(VLANClientState *backend, int devfd)
+{
+	return NULL;
+}
+
+int vhost_net_start(struct vhost_net *net,
+		    VirtIODevice *dev)
+{
+	return -ENOSYS;
+}
+void vhost_net_stop(struct vhost_net *net,
+		    VirtIODevice *dev)
+{
+}
+
+void vhost_net_cleanup(struct vhost_net *net)
+{
+}
+
+unsigned vhost_net_get_features(struct vhost_net *net, unsigned features)
+{
+	return features;
+}
+void vhost_net_ack_features(struct vhost_net *net, unsigned features)
+{
+}
+#endif

qemu-vhost-vhost-net-support.patch:
 Makefile.target |    1 
 hw/vhost.c      |  603 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 hw/vhost.h      |   44 ++++
 hw/vhost_net.c  |  147 +++++++++++++
 hw/vhost_net.h  |   21 +
 5 files changed, 815 insertions(+), 1 deletion(-)

--- NEW FILE qemu-vhost-vhost-net-support.patch ---
This adds vhost net support in qemu. Will be tied to tap device and
virtio by following patches.  Raw backend is currently missing, will be
worked on/submitted separately.

Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
---
 Makefile.target |    1 +
 hw/vhost.c      |  603 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 hw/vhost.h      |   44 ++++
 hw/vhost_net.c  |  147 ++++++++++++++
 hw/vhost_net.h  |   20 ++
 5 files changed, 815 insertions(+), 0 deletions(-)
 create mode 100644 hw/vhost.c
 create mode 100644 hw/vhost.h
 create mode 100644 hw/vhost_net.c
 create mode 100644 hw/vhost_net.h

diff --git a/Makefile.target b/Makefile.target
index 0c844a9..2ebd30c 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -168,6 +168,7 @@ obj-y = vl.o async.o monitor.o pci.o pci_host.o pcie_host.o machine.o gdbstub.o
 # need to fix this properly
 obj-y += virtio-blk.o virtio-balloon.o virtio-net.o virtio-pci.o virtio-serial-bus.o
 obj-y += notifier.o
+obj-y += vhost_net.o vhost.o
 obj-$(CONFIG_KVM) += kvm.o kvm-all.o
 # MSI-X depends on kvm for interrupt injection,
 # so moved it from Makefile.hw to Makefile.target for now
diff --git a/hw/vhost.c b/hw/vhost.c
new file mode 100644
index 0000000..e5c1ead
--- /dev/null
+++ b/hw/vhost.c
@@ -0,0 +1,603 @@
+#include "linux/vhost.h"
+#include <sys/ioctl.h>
+#include <sys/eventfd.h>
+#include "vhost.h"
+#include "hw/hw.h"
+/* For range_get_last */
+#include "pci.h"
+
+static void vhost_dev_sync_region(struct vhost_dev *dev,
+				     uint64_t mfirst, uint64_t mlast,
+				     uint64_t rfirst, uint64_t rlast)
+{
+	uint64_t start = MAX(mfirst, rfirst);
+	uint64_t end = MIN(mlast, rlast);
+	vhost_log_chunk_t *from = dev->log + start / VHOST_LOG_CHUNK;
+	vhost_log_chunk_t *to = dev->log + end / VHOST_LOG_CHUNK + 1;
+	uint64_t addr = (start / VHOST_LOG_CHUNK) * VHOST_LOG_CHUNK;
+
+	assert(end / VHOST_LOG_CHUNK < dev->log_size);
+	assert(start / VHOST_LOG_CHUNK < dev->log_size);
+	if (end < start) {
+		return;
+	}
+	for (;from < to; ++from) {
+		vhost_log_chunk_t log;
+		int bit;
+		/* We first check with non-atomic: much cheaper,
+		 * and we expect non-dirty to be the common case. */
+		if (!*from) {
+			continue;
+		}
+		/* Data must be read atomically. We don't really
+		 * need the barrier semantics of __sync
+		 * builtins, but it's easier to use them than
+		 * roll our own. */
+		log = __sync_fetch_and_and(from, 0);
+		while ((bit = sizeof(log) > sizeof(int) ?
+		       ffsll(log) : ffs(log))) {
+			bit -= 1;
+			cpu_physical_memory_set_dirty(addr + bit * VHOST_LOG_PAGE);
+			log &= ~(0x1ull << bit);
+		}
+		addr += VHOST_LOG_CHUNK;
+	}
+}
+
+static int vhost_client_sync_dirty_bitmap(struct CPUPhysMemoryClient *client,
+					target_phys_addr_t start_addr,
+					target_phys_addr_t end_addr)
+{
+	struct vhost_dev *dev = container_of(client, struct vhost_dev, client);
+	int i;
+	if (!dev->log_enabled || !dev->started) {
+		return 0;
+	}
+	for (i = 0; i < dev->mem->nregions; ++i) {
+		struct vhost_memory_region *reg = dev->mem->regions + i;
+		vhost_dev_sync_region(dev, start_addr, end_addr,
+				      reg->guest_phys_addr,
+				      range_get_last(reg->guest_phys_addr,
+						     reg->memory_size));
+	}
+	for (i = 0; i < dev->nvqs; ++i) {
+		struct vhost_virtqueue *vq = dev->vqs + i;
+		unsigned size = sizeof(struct vring_used_elem) * vq->num;
+		vhost_dev_sync_region(dev, start_addr, end_addr, vq->used_phys,
+				      range_get_last(vq->used_phys, size));
+	}
+	return 0;
+}
+
+/* Assign/unassign. Keep an unsorted array of non-overlapping
+ * memory regions in dev->mem. */
+static void vhost_dev_unassign_memory(struct vhost_dev *dev,
+				      uint64_t start_addr,
+				      uint64_t size)
+{
+	int from, to, n = dev->mem->nregions;
+	/* Track overlapping/split regions for sanity checking. */
+	int overlap_start = 0, overlap_end = 0, overlap_middle = 0, split = 0;
+
+	for (from = 0, to = 0; from < n; ++from, ++to) {
+		struct vhost_memory_region *reg = dev->mem->regions + to;
+		uint64_t reglast;
+		uint64_t memlast;
+		uint64_t change;
+
+		/* clone old region */
+		if (to != from) {
+			memcpy(reg, dev->mem->regions + from, sizeof *reg);
+		}
+
+		/* No overlap is simple */
+		if (!ranges_overlap(reg->guest_phys_addr, reg->memory_size,
+				    start_addr, size)) {
+			continue;
+		}
+
+		/* Split only happens if supplied region
+		 * is in the middle of an existing one. Thus it can not
+		 * overlap with any other existing region. */
+		assert(!split);
+
+		reglast = range_get_last(reg->guest_phys_addr, reg->memory_size);
+		memlast = range_get_last(start_addr, size);
+
+		/* Remove whole region */
+		if (start_addr <= reg->guest_phys_addr && memlast >= reglast) {
+			--dev->mem->nregions;
+			--to;
+			assert(to >= 0);
+			++overlap_middle;
+			continue;
+		}
+
+		/* Shrink region */
+		if (memlast >= reglast) {
+			reg->memory_size = start_addr - reg->guest_phys_addr;
+			assert(reg->memory_size);
+			assert(!overlap_end);
+			++overlap_end;
+			continue;
+		}
+
+		/* Shift region */
+		if (start_addr <= reg->guest_phys_addr) {
+			change = memlast + 1 - reg->guest_phys_addr;
+			reg->memory_size -= change;
+			reg->guest_phys_addr += change;
+			reg->userspace_addr += change;
+			assert(reg->memory_size);
+			assert(!overlap_start);
+			++overlap_start;
+			continue;
+		}
+
+		/* This only happens if supplied region
+		 * is in the middle of an existing one. Thus it can not
+		 * overlap with any other existing region. */
+		assert(!overlap_start);
+		assert(!overlap_end);
+		assert(!overlap_middle);
+		/* Split region: shrink first part, shift second part. */
+		memcpy(dev->mem->regions + n, reg, sizeof *reg);
+		reg->memory_size = start_addr - reg->guest_phys_addr;
+		assert(reg->memory_size);
+		change = memlast + 1 - reg->guest_phys_addr;
+		reg = dev->mem->regions + n;
+		reg->memory_size -= change;
+		assert(reg->memory_size);
+		reg->guest_phys_addr += change;
+		reg->userspace_addr += change;
+		/* Never add more than 1 region */
+		assert(dev->mem->nregions == n);
+		++dev->mem->nregions;
+		++split;
+	}
+}
+
+/* Called after unassign, so no regions overlap the given range. */
+static void vhost_dev_assign_memory(struct vhost_dev *dev,
+				    uint64_t start_addr,
+				    uint64_t size,
+				    uint64_t uaddr)
+{
+	int from, to;
+	struct vhost_memory_region *merged = NULL;
+	for (from = 0, to = 0; from < dev->mem->nregions; ++from, ++to) {
+		struct vhost_memory_region *reg = dev->mem->regions + to;
+		uint64_t prlast, urlast;
+		uint64_t pmlast, umlast;
+		uint64_t s, e, u;
+
+		/* clone old region */
+		if (to != from) {
+			memcpy(reg, dev->mem->regions + from, sizeof *reg);
+		}
+		prlast = range_get_last(reg->guest_phys_addr, reg->memory_size);
+		pmlast = range_get_last(start_addr, size);
+		urlast = range_get_last(reg->userspace_addr, reg->memory_size);
+		umlast = range_get_last(uaddr, size);
+
+		/* check for overlapping regions: should never happen. */
+		assert(prlast < start_addr || pmlast < reg->guest_phys_addr);
+		/* Not an adjacent or overlapping region - do not merge. */
+		if ((prlast + 1 != start_addr || urlast + 1 != uaddr) &&
+		    (pmlast + 1 != reg->guest_phys_addr ||
+		     umlast + 1 != reg->userspace_addr)) {
+			continue;
+		}
+
+		if (merged) {
+			--to;
+			assert(to >= 0);
+		} else {
+			merged = reg;
+		}
+		u = MIN(uaddr, reg->userspace_addr);
+		s = MIN(start_addr, reg->guest_phys_addr);
+		e = MAX(pmlast, prlast);
+		uaddr = merged->userspace_addr = u;
+		start_addr = merged->guest_phys_addr = s;
+		size = merged->memory_size = e - s + 1;
+		assert(merged->memory_size);
+	}
+
+	if (!merged) {
+		struct vhost_memory_region *reg = dev->mem->regions + to;
+		memset(reg, 0, sizeof *reg);
+		reg->memory_size = size;
+		assert(reg->memory_size);
+		reg->guest_phys_addr = start_addr;
+		reg->userspace_addr = uaddr;
+		++to;
+	}
+	assert(to <= dev->mem->nregions + 1);
+	dev->mem->nregions = to;
+}
+
+static uint64_t vhost_get_log_size(struct vhost_dev *dev)
+{
+	uint64_t log_size = 0;
+	int i;
+	for (i = 0; i < dev->mem->nregions; ++i) {
+		struct vhost_memory_region *reg = dev->mem->regions + i;
+		uint64_t last = range_get_last(reg->guest_phys_addr,
+					       reg->memory_size);
+		log_size = MAX(log_size, last / VHOST_LOG_CHUNK + 1);
+	}
+	for (i = 0; i < dev->nvqs; ++i) {
+		struct vhost_virtqueue *vq = dev->vqs + i;
+		uint64_t last = vq->used_phys +
+			sizeof(struct vring_used_elem) * vq->num - 1;
+		log_size = MAX(log_size, last / VHOST_LOG_CHUNK + 1);
+	}
+	return log_size;
+}
+
+static inline void vhost_dev_log_resize(struct vhost_dev* dev, uint64_t size)
+{
+	vhost_log_chunk_t *log;
+	int r;
+	if (size) {
+		log = qemu_mallocz(size * sizeof *log);
+	} else {
+		log = NULL;
+	}
+	r = ioctl(dev->control, VHOST_SET_LOG_BASE,
+		  (uint64_t)(unsigned long)log);
+	assert(r >= 0);
+	vhost_client_sync_dirty_bitmap(&dev->client, 0,
+				       (target_phys_addr_t)~0x0ull);
+	if (dev->log) {
+		qemu_free(dev->log);
+	}
+	dev->log = log;
+	dev->log_size = size;
+}
+
+static void vhost_client_set_memory(CPUPhysMemoryClient *client,
+				    target_phys_addr_t start_addr,
+				    ram_addr_t size,
+				    ram_addr_t phys_offset)
+{
+	struct vhost_dev *dev = container_of(client, struct vhost_dev, client);
+	ram_addr_t flags = phys_offset & ~TARGET_PAGE_MASK;
+	int s = offsetof(struct vhost_memory, regions) +
+		(dev->mem->nregions + 1) * sizeof dev->mem->regions[0];
+	uint64_t log_size;
+	int r;
+	dev->mem = qemu_realloc(dev->mem, s);
+
+	assert(size);
+
+	vhost_dev_unassign_memory(dev, start_addr, size);
+	if (flags == IO_MEM_RAM) {
+		/* Add given mapping, merging adjacent regions if any */
+		vhost_dev_assign_memory(dev, start_addr, size,
+				(uintptr_t)qemu_get_ram_ptr(phys_offset));
+	} else {
+		/* Remove old mapping for this memory, if any. */
+		vhost_dev_unassign_memory(dev, start_addr, size);
+	}
+
+	if (!dev->started) {
+		return;
+	}
+	if (!dev->log_enabled) {
+		r = ioctl(dev->control, VHOST_SET_MEM_TABLE, dev->mem);
+		assert(r >= 0);
+		return;
+	}
+	log_size = vhost_get_log_size(dev);
+	/* We allocate an extra 4K bytes to log,
+	 * to reduce the * number of reallocations. */
+#define VHOST_LOG_BUFFER (0x1000 / sizeof *dev->log)
+	/* To log more, must increase log size before table update. */
+	if (dev->log_size < log_size) {
+		vhost_dev_log_resize(dev, log_size + VHOST_LOG_BUFFER);
+	}
+	r = ioctl(dev->control, VHOST_SET_MEM_TABLE, dev->mem);
+	assert(r >= 0);
+	/* To log less, can only decrease log size after table update. */
+	if (dev->log_size > log_size + VHOST_LOG_BUFFER) {
+		vhost_dev_log_resize(dev, log_size);
+	}
+}
+
+static int vhost_dev_set_log(struct vhost_dev *dev, bool enable_log)
+{
+	uint64_t features = dev->acked_features;
+	int r;
+	if (dev->log_enabled) {
+		features |= 0x1 << VHOST_F_LOG_ALL;
+	}
+	r = ioctl(dev->control, VHOST_SET_FEATURES, &features);
+	return r < 0 ? -errno : 0;
+}
+
+static int vhost_client_migration_log(struct CPUPhysMemoryClient *client,
+				      int enable)
+{
+	struct vhost_dev *dev = container_of(client, struct vhost_dev, client);
+	int r;
+	if (!!enable == dev->log_enabled) {
+		return 0;
+	}
+	if (!dev->started) {
+		dev->log_enabled = enable;
+		return 0;
+	}
+	if (!enable) {
+		r = vhost_dev_set_log(dev, false);
+		if (r < 0) {
+			return r;
+		}
+		if (dev->log) {
+			qemu_free(dev->log);
+		}
+		dev->log = NULL;
+		dev->log_size = 0;
+	} else {
+		vhost_dev_log_resize(dev, vhost_get_log_size(dev));
+		r = vhost_dev_set_log(dev, false);
+		if (r < 0) {
+			return r;
+		}
+	}
+	dev->log_enabled = enable;
+	return 0;
+}
+
+static int vhost_virtqueue_set_addr(struct vhost_dev *dev,
+				    struct vhost_virtqueue *vq,
+				    unsigned idx, bool enable_log)
+{
+	struct vhost_vring_addr addr = {
+		.index = idx,
+		.desc_user_addr = (u_int64_t)(unsigned long)vq->desc,
+		.avail_user_addr = (u_int64_t)(unsigned long)vq->avail,
+		.used_user_addr = (u_int64_t)(unsigned long)vq->used,
+		.log_guest_addr = vq->used_phys,
+		.flags = enable_log ? (1 << VHOST_VRING_F_LOG) : 0,
+	};
+	int r = ioctl(dev->control, VHOST_SET_VRING_ADDR, &addr);
+	if (r < 0) {
+		return -errno;
+	}
+	return 0;
+}
+
+static int vhost_virtqueue_init(struct vhost_dev *dev,
+				struct VirtIODevice *vdev,
+				struct vhost_virtqueue *vq,
+				unsigned idx)
+{
+	target_phys_addr_t s, l, a;
+	int r;
+	struct vhost_vring_file file = {
+		.index = idx,
+	};
+	struct vhost_vring_state state = {
+		.index = idx,
+	};
+	struct VirtQueue *q = virtio_queue(vdev, idx);
+
+	vq->num = state.num = virtio_queue_get_num(vdev, idx);
+	r = ioctl(dev->control, VHOST_SET_VRING_NUM, &state);
+	if (r) {
+		return -errno;
+	}
+
+	state.num = virtio_queue_last_avail_idx(vdev, idx);
+	r = ioctl(dev->control, VHOST_SET_VRING_BASE, &state);
+	if (r) {
+		return -errno;
+	}
+
+	s = l = sizeof(struct vring_desc) * vq->num;
+	a = virtio_queue_get_desc(vdev, idx);
+	vq->desc = cpu_physical_memory_map(a, &l, 0);
+	if (!vq->desc || l != s) {
+		r = -ENOMEM;
+		goto fail_alloc;
+	}
+	s = l = offsetof(struct vring_avail, ring) +
+		sizeof(u_int64_t) * vq->num;
+	a = virtio_queue_get_avail(vdev, idx);
+	vq->avail = cpu_physical_memory_map(a, &l, 0);
+	if (!vq->avail || l != s) {
+		r = -ENOMEM;
+		goto fail_alloc;
+	}
+	s = l = offsetof(struct vring_used, ring) +
+		sizeof(struct vring_used_elem) * vq->num;
+	vq->used_phys = a = virtio_queue_get_used(vdev, idx);
+	vq->used = cpu_physical_memory_map(a, &l, 1);
+	if (!vq->used || l != s) {
+		r = -ENOMEM;
+		goto fail_alloc;
+	}
+
+	r = vhost_virtqueue_set_addr(dev, vq, idx, dev->log_enabled);
+	if (r < 0) {
+		r = -errno;
+		goto fail_alloc;
+	}
+	if (!vdev->binding->guest_notifier || !vdev->binding->host_notifier) {
+		fprintf(stderr, "binding does not support irqfd/queuefd\n");
+		r = -ENOSYS;
+		goto fail_alloc;
+	}
+        r = vdev->binding->guest_notifier(vdev->binding_opaque, idx, true);
+	if (r < 0) {
+		fprintf(stderr, "Error binding guest notifier: %d\n", -r);
+		goto fail_guest_notifier;
+	}
+
+        r = vdev->binding->host_notifier(vdev->binding_opaque, idx, true);
+	if (r < 0) {
+		fprintf(stderr, "Error binding host notifier: %d\n", -r);
+		goto fail_host_notifier;
+	}
+
+	file.fd = event_notifier_get_fd(virtio_queue_host_notifier(q));
+	r = ioctl(dev->control, VHOST_SET_VRING_KICK, &file);
+	if (r) {
+		goto fail_kick;
+	}
+
+	file.fd = event_notifier_get_fd(virtio_queue_guest_notifier(q));
+	r = ioctl(dev->control, VHOST_SET_VRING_CALL, &file);
+	if (r) {
+		goto fail_call;
+	}
+
+	return 0;
+
+fail_call:
+fail_kick:
+        vdev->binding->host_notifier(vdev->binding_opaque, idx, false);
+fail_host_notifier:
+        vdev->binding->guest_notifier(vdev->binding_opaque, idx, false);
+fail_guest_notifier:
+fail_alloc:
+	return r;
+}
+
+static void vhost_virtqueue_cleanup(struct vhost_dev *dev,
+				    struct VirtIODevice *vdev,
+				    struct vhost_virtqueue *vq,
+				    unsigned idx)
+{
+	struct vhost_vring_state state = {
+		.index = idx,
+	};
+	int r;
+	r = vdev->binding->guest_notifier(vdev->binding_opaque, idx, false);
+	if (r < 0) {
+		fprintf(stderr, "vhost VQ %d guest cleanup failed: %d\n", idx, r);
+		fflush(stderr);
+	}
+	assert (r >= 0);
+
+	r = vdev->binding->host_notifier(vdev->binding_opaque, idx, false);
+	if (r < 0) {
+		fprintf(stderr, "vhost VQ %d host cleanup failed: %d\n", idx, r);
+		fflush(stderr);
+	}
+	assert (r >= 0);
+	r = ioctl(dev->control, VHOST_GET_VRING_BASE, &state);
+	if (r < 0) {
+		fprintf(stderr, "vhost VQ %d ring restore failed: %d\n", idx, r);
+		fflush(stderr);
+	}
+	virtio_queue_set_last_avail_idx(vdev, idx, state.num);
+	assert (r >= 0);
+}
+
+int vhost_dev_init(struct vhost_dev *hdev, int devfd)
+{
+	uint64_t features;
+	int r;
+	if (devfd >= 0) {
+		hdev->control = devfd;
+	} else {
+		hdev->control = open("/dev/vhost-net", O_RDWR);
+		if (hdev->control < 0)
+			return -errno;
+	}
+	r = ioctl(hdev->control, VHOST_SET_OWNER, NULL);
+	if (r < 0)
+		goto fail;
+
+	r = ioctl(hdev->control, VHOST_GET_FEATURES, &features);
+	if (r < 0)
+		goto fail;
+	hdev->features = features;
+	
+	hdev->client.set_memory = vhost_client_set_memory;
+	hdev->client.sync_dirty_bitmap = vhost_client_sync_dirty_bitmap;
+	hdev->client.migration_log = vhost_client_migration_log;
+	hdev->mem = qemu_mallocz(offsetof(struct vhost_memory, regions));
+	hdev->log = NULL;
+	hdev->log_size = 0;
+	hdev->log_enabled = false;
+	hdev->started = false;
+	cpu_register_phys_memory_client(&hdev->client);
+	return 0;
+fail:
+	r = -errno;
+	close(hdev->control);
+	return r;
+}
+
+void vhost_dev_cleanup(struct vhost_dev *hdev)
+{
+	cpu_unregister_phys_memory_client(&hdev->client);
+	qemu_free(hdev->mem);
+	close(hdev->control);
+}
+
+int vhost_dev_start(struct vhost_dev *hdev, VirtIODevice *vdev)
+{
+	int i, r;
+
+	r = vhost_dev_set_log(hdev, hdev->log_enabled);
+	if (r < 0)
+		goto fail;
+	r = ioctl(hdev->control, VHOST_SET_MEM_TABLE, hdev->mem);
+	if (r < 0) {
+		r = -errno;
+		goto fail;
+	}
+	if (hdev->log_enabled) {
+		hdev->log_size = vhost_get_log_size(hdev);
+		hdev->log = hdev->log_size ?
+			qemu_mallocz(hdev->log_size * sizeof *hdev->log) : NULL;
+		r = ioctl(hdev->control, VHOST_SET_LOG_BASE,
+			  (uint64_t)(unsigned long)hdev->log);
+		if (r < 0) {
+			r = -errno;
+			goto fail;
+		}
+	}
+
+	for (i = 0; i < hdev->nvqs; ++i) {
+		r = vhost_virtqueue_init(hdev,
+		   			 vdev,
+					 hdev->vqs + i,
+					 i);
+		if (r < 0)
+			goto fail_vq;
+	}
+	hdev->started = true;
+
+	return 0;
+fail_vq:
+	while (--i >= 0) {
+		vhost_virtqueue_cleanup(hdev,
+					vdev,
+					hdev->vqs + i,
+					i);
+	}
+fail:
+	return r;
+}
+
+void vhost_dev_stop(struct vhost_dev *hdev, VirtIODevice *vdev)
+{
+	int i;
+	for (i = 0; i < hdev->nvqs; ++i) {
+		vhost_virtqueue_cleanup(hdev,
+					vdev,
+					hdev->vqs + i,
+					i);
+	}
+	vhost_client_sync_dirty_bitmap(&hdev->client, 0,
+				       (target_phys_addr_t)~0x0ull);
+	hdev->started = false;
+	qemu_free(hdev->log);
+	hdev->log_size = 0;
+}
diff --git a/hw/vhost.h b/hw/vhost.h
new file mode 100644
index 0000000..2ed3933
--- /dev/null
+++ b/hw/vhost.h
@@ -0,0 +1,44 @@
+#ifndef VHOST_H
+#define VHOST_H
+
+#include "hw/hw.h"
+#include "hw/virtio.h"
+
+/* Generic structures common for any vhost based device. */
+struct vhost_virtqueue {
+	int kick;
+	int call;
+	void *desc;
+	void *avail;
+	void *used;
+	int num;
+	unsigned long long used_phys;
+};
+
+typedef unsigned long vhost_log_chunk_t;
+#define VHOST_LOG_PAGE 0x1000
+#define VHOST_LOG_BITS (8 * sizeof(vhost_log_chunk_t))
+#define VHOST_LOG_CHUNK (VHOST_LOG_PAGE * VHOST_LOG_BITS)
+
+struct vhost_memory;
+struct vhost_dev {
+	CPUPhysMemoryClient client;
+	int control;
+	struct vhost_memory *mem;
+	struct vhost_virtqueue *vqs;
+	int nvqs;
+	unsigned long long features;
+	unsigned long long acked_features;
+	unsigned long long backend_features;
+	bool started;
+	bool log_enabled;
+	vhost_log_chunk_t *log;
+	unsigned long long log_size;
+};
+
+int vhost_dev_init(struct vhost_dev *hdev, int devfd);
+void vhost_dev_cleanup(struct vhost_dev *hdev);
+int vhost_dev_start(struct vhost_dev *hdev, VirtIODevice *vdev);
+void vhost_dev_stop(struct vhost_dev *hdev, VirtIODevice *vdev);
+
+#endif
diff --git a/hw/vhost_net.c b/hw/vhost_net.c
new file mode 100644
index 0000000..c89ff40
--- /dev/null
+++ b/hw/vhost_net.c
@@ -0,0 +1,147 @@
+#include <sys/eventfd.h>
+#include <sys/socket.h>
+#include <linux/kvm.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <linux/vhost.h>
+#include <linux/virtio_ring.h>
+#include <netpacket/packet.h>
+#include <net/ethernet.h>
+#include <net/if.h>
+#include <netinet/in.h>
+
+#include <stdio.h>
+
+#include "net.h"
+#include "net/tap.h"
+
+#include "virtio-net.h"
+#include "vhost.h"
+#include "vhost_net.h"
+
+struct vhost_net {
+	struct vhost_dev dev;
+	struct vhost_virtqueue vqs[2];
+	int backend;
+	VLANClientState *vc;
+};
+
+unsigned vhost_net_get_features(struct vhost_net *net, unsigned features)
+{
+	/* Clear features not supported by host kernel. */
+	if (!(net->dev.features & (1 << VIRTIO_F_NOTIFY_ON_EMPTY)))
+		features &= ~(1 << VIRTIO_F_NOTIFY_ON_EMPTY);
+	if (!(net->dev.features & (1 << VIRTIO_RING_F_INDIRECT_DESC)))
+		features &= ~(1 << VIRTIO_RING_F_INDIRECT_DESC);
+	if (!(net->dev.features & (1 << VIRTIO_NET_F_MRG_RXBUF)))
+		features &= ~(1 << VIRTIO_NET_F_MRG_RXBUF);
+	return features;
+}
+
+void vhost_net_ack_features(struct vhost_net *net, unsigned features)
+{
+	net->dev.acked_features = net->dev.backend_features;
+	if (features & (1 << VIRTIO_F_NOTIFY_ON_EMPTY))
+		net->dev.acked_features |= (1 << VIRTIO_F_NOTIFY_ON_EMPTY);
+	if (features & (1 << VIRTIO_RING_F_INDIRECT_DESC))
+		net->dev.acked_features |= (1 << VIRTIO_RING_F_INDIRECT_DESC);
+}
+
+static int vhost_net_get_fd(VLANClientState *backend)
+{
+	switch (backend->info->type) {
+	case NET_CLIENT_TYPE_TAP:
+		return tap_get_fd(backend);
+	default:
+		fprintf(stderr, "vhost-net requires tap backend\n");
+		return -EBADFD;
+	}
+}
+
+struct vhost_net *vhost_net_init(VLANClientState *backend, int devfd)
+{
+	int r;
+	struct vhost_net *net = qemu_malloc(sizeof *net);
+	if (!backend) {
+		fprintf(stderr, "vhost-net requires backend to be setup\n");
+		goto fail;
+	}
+	r = vhost_net_get_fd(backend);
+	if (r < 0)
+		goto fail;
+	net->vc = backend;
+	net->dev.backend_features = tap_has_vnet_hdr(backend) ? 0 :
+		(1 << VHOST_NET_F_VIRTIO_NET_HDR);
+	net->backend = r;
+
+	r = vhost_dev_init(&net->dev, devfd);
+	if (r < 0)
+		goto fail;
+	if (~net->dev.features & net->dev.backend_features) {
+		fprintf(stderr, "vhost lacks feature mask %llu for backend\n",
+			~net->dev.features & net->dev.backend_features);
+		vhost_dev_cleanup(&net->dev);
+		goto fail;
+	}
+
+	/* Set sane init value. Override when guest acks. */
+	vhost_net_ack_features(net, 0);
+	return net;
+fail:
+	qemu_free(net);
+	return NULL;
+}
+
+int vhost_net_start(struct vhost_net *net,
+		    VirtIODevice *dev)
+{
+	struct vhost_vring_file file = { };
+	int r;
+
+	net->dev.nvqs = 2;
+	net->dev.vqs = net->vqs;
+	r = vhost_dev_start(&net->dev, dev);
+	if (r < 0)
+		return r;
+
+	net->vc->info->poll(net->vc, false);
+	qemu_set_fd_handler(net->backend, NULL, NULL, NULL);
+	file.fd = net->backend;
+	for (file.index = 0; file.index < net->dev.nvqs; ++file.index) {
+		r = ioctl(net->dev.control, VHOST_NET_SET_BACKEND, &file);
+		if (r < 0) {
+			r = -errno;
+			goto fail;
+		}
+	}
+	return 0;
+fail:
+	file.fd = -1;
+	while (--file.index >= 0) {
+		int r = ioctl(net->dev.control, VHOST_NET_SET_BACKEND, &file);
+		assert(r >= 0);
+	}
+	net->vc->info->poll(net->vc, true);
+	vhost_dev_stop(&net->dev, dev);
+	return r;
+}
+
+void vhost_net_stop(struct vhost_net *net,
+		    VirtIODevice *dev)
+{
+	struct vhost_vring_file file = { .fd = -1 };
+
+	for (file.index = 0; file.index < net->dev.nvqs; ++file.index) {
+		int r = ioctl(net->dev.control, VHOST_NET_SET_BACKEND, &file);
+		assert(r >= 0);
+	}
+	net->vc->info->poll(net->vc, true);
+	vhost_dev_stop(&net->dev, dev);
+}
+
+void vhost_net_cleanup(struct vhost_net *net)
+{
+	vhost_dev_cleanup(&net->dev);
+	qemu_free(net);
+}
+/* TODO: log */
diff --git a/hw/vhost_net.h b/hw/vhost_net.h
new file mode 100644
index 0000000..21f0277
--- /dev/null
+++ b/hw/vhost_net.h
@@ -0,0 +1,20 @@
+#ifndef VHOST_NET_H
+#define VHOST_NET_H
+
+#include "net.h"
+
+struct vhost_net;
+
+struct vhost_net *vhost_net_init(VLANClientState *backend, int devfd);
+
+int vhost_net_start(struct vhost_net *net,
+		    VirtIODevice *dev);
+void vhost_net_stop(struct vhost_net *net,
+		    VirtIODevice *dev);
+
+void vhost_net_cleanup(struct vhost_net *net);
+
+unsigned vhost_net_get_features(struct vhost_net *net, unsigned features);
+void vhost_net_ack_features(struct vhost_net *net, unsigned features);
+
+#endif
-- 
1.6.6.144.g5c3af

qemu-virtio-add-APIs-for-queue-fields.patch:
 virtio.c |   51 +++++++++++++++++++++++++++++++++++++++++++++++----
 virtio.h |   11 +++++++++--
 2 files changed, 56 insertions(+), 6 deletions(-)

--- NEW FILE qemu-virtio-add-APIs-for-queue-fields.patch ---
vhost needs physical addresses for ring and other queue fields,
so add APIs for these.

Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
---
 hw/virtio.c |   51 +++++++++++++++++++++++++++++++++++++++++++++++----
 hw/virtio.h |   10 +++++++++-
 2 files changed, 56 insertions(+), 5 deletions(-)

diff --git a/hw/virtio.c b/hw/virtio.c
index c2b80aa..b16ee1a 100644
--- a/hw/virtio.c
+++ b/hw/virtio.c
@@ -73,6 +73,9 @@ struct VirtQueue
     int inuse;
     uint16_t vector;
     void (*handle_output)(VirtIODevice *vdev, VirtQueue *vq);
+    VirtIODevice *vdev;
+    EventNotifier guest_notifier;
+    EventNotifier host_notifier;
 };
 
 /* virt queue functions */
@@ -594,10 +597,10 @@ VirtQueue *virtio_add_queue(VirtIODevice *vdev, int queue_size,
     return &vdev->vq[i];
 }
 
-void virtio_irq(VirtIODevice *vdev, VirtQueue *vq)
+void virtio_irq(VirtQueue *vq)
 {
-    vdev->isr |= 0x01;
-    virtio_notify_vector(vdev, vq->vector);
+    vq->vdev->isr |= 0x01;
+    virtio_notify_vector(vq->vdev, vq->vector);
 }
 
 void virtio_notify(VirtIODevice *vdev, VirtQueue *vq)
@@ -608,7 +611,8 @@ void virtio_notify(VirtIODevice *vdev, VirtQueue *vq)
          (vq->inuse || vring_avail_idx(vq) != vq->last_avail_idx)))
         return;
 
-    virtio_irq(vdev, vq);
+    vdev->isr |= 0x01;
+    virtio_notify_vector(vdev, vq->vector);
 }
 
 void virtio_notify_config(VirtIODevice *vdev)
@@ -742,3 +746,42 @@ void virtio_bind_device(VirtIODevice *vdev, const VirtIOBindings *binding,
     vdev->binding = binding;
     vdev->binding_opaque = opaque;
 }
+
+target_phys_addr_t virtio_queue_get_desc(VirtIODevice *vdev, int n)
+{
+	return vdev->vq[n].vring.desc;
+}
+
+target_phys_addr_t virtio_queue_get_avail(VirtIODevice *vdev, int n)
+{
+	return vdev->vq[n].vring.avail;
+}
+
+target_phys_addr_t virtio_queue_get_used(VirtIODevice *vdev, int n)
+{
+	return vdev->vq[n].vring.used;
+}
+
+uint16_t virtio_queue_last_avail_idx(VirtIODevice *vdev, int n)
+{
+	return vdev->vq[n].last_avail_idx;
+}
+
+void virtio_queue_set_last_avail_idx(VirtIODevice *vdev, int n, uint16_t idx)
+{
+	vdev->vq[n].last_avail_idx = idx;
+}
+
+VirtQueue *virtio_queue(VirtIODevice *vdev, int n)
+{
+	return vdev->vq + n;
+}
+
+EventNotifier *virtio_queue_guest_notifier(VirtQueue *vq)
+{
+	return &vq->guest_notifier;
+}
+EventNotifier *virtio_queue_host_notifier(VirtQueue *vq)
+{
+	return &vq->host_notifier;
+}
diff --git a/hw/virtio.h b/hw/virtio.h
index 10a0959..f140ca3 100644
--- a/hw/virtio.h
+++ b/hw/virtio.h
@@ -183,5 +183,13 @@ void virtio_net_exit(VirtIODevice *vdev);
 	DEFINE_PROP_BIT("indirect_desc", _state, _field, \
 			VIRTIO_RING_F_INDIRECT_DESC, true)
 
-void virtio_irq(VirtIODevice *vdev, VirtQueue *vq);
+target_phys_addr_t virtio_queue_get_desc(VirtIODevice *vdev, int n);
+target_phys_addr_t virtio_queue_get_avail(VirtIODevice *vdev, int n);
+target_phys_addr_t virtio_queue_get_used(VirtIODevice *vdev, int n);
+uint16_t virtio_queue_last_avail_idx(VirtIODevice *vdev, int n);
+void virtio_queue_set_last_avail_idx(VirtIODevice *vdev, int n, uint16_t idx);
+VirtQueue *virtio_queue(VirtIODevice *vdev, int n);
+EventNotifier *virtio_queue_guest_notifier(VirtQueue *vq);
+EventNotifier *virtio_queue_host_notifier(VirtQueue *vq);
+void virtio_irq(VirtQueue *vq);
 #endif
-- 
1.6.6.144.g5c3af

qemu-virtio-add-features-as-qdev-properties.patch:
 hw/s390-virtio-bus.c |   12 +++++++++---
 hw/syborg_virtio.c   |   13 ++++++++-----
 hw/virtio-balloon.c  |    4 ++--
 hw/virtio-blk.c      |    6 +-----
 hw/virtio-blk.h      |    8 ++++++++
 hw/virtio-net.c      |   39 ++++++++++++++++-----------------------
 hw/virtio-net.h      |   20 ++++++++++++++++++++
 hw/virtio-pci.c      |   25 +++++++++++++++++--------
 hw/virtio.c          |    2 +-
 s390-virtio-bus.h    |    1 +
 virtio.h             |    7 ++++++-
 11 files changed, 89 insertions(+), 48 deletions(-)

--- NEW FILE qemu-virtio-add-features-as-qdev-properties.patch ---
Add feature bits as properties to virtio. This makes it possible to e.g. define
machine without indirect buffer support, which is required for 0.10
compatibility, or without hardware checksum support, which is required for 0.11
compatibility.  Since default values for optional features are now set by qdev,
get_features callback has been modified: it sets non-optional bits, and clears
bits not supported by host.

Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
Acked-by: Gerd Hoffmann <kraxel at redhat.com>
Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
(cherry picked from commit 8172539d21a03e982aa7f139ddc1607dc1422045)
---
 hw/s390-virtio-bus.c |   12 +++++++++---
 hw/s390-virtio-bus.h |    1 +
 hw/syborg_virtio.c   |   13 ++++++++-----
 hw/virtio-balloon.c  |    4 ++--
 hw/virtio-blk.c      |    6 +-----
 hw/virtio-blk.h      |    8 ++++++++
 hw/virtio-net.c      |   39 ++++++++++++++++-----------------------
 hw/virtio-net.h      |   20 ++++++++++++++++++++
 hw/virtio-pci.c      |   25 +++++++++++++++++--------
 hw/virtio.c          |    2 +-
 hw/virtio.h          |    7 ++++++-
 12 files changed, 91 insertions(+), 50 deletions(-)

--- a/hw/s390-virtio-bus.c	2010-02-09 00:18:58.000000000 -0600
+++ b/hw/s390-virtio-bus.c	2010-02-09 00:02:12.000000000 -0600
@@ -101,6 +101,7 @@ static int s390_virtio_device_init(VirtI
     bus->dev_offs += dev_len;
 
     virtio_bind_device(vdev, &virtio_s390_bindings, dev);
+    dev->host_features = vdev->get_features(vdev, dev->host_features);
     s390_virtio_device_sync(dev);
 
     return 0;
@@ -222,9 +223,7 @@ static void s390_virtio_device_sync(Virt
     cur_offs += num_vq * VIRTIO_VQCONFIG_LEN;
 
     /* Sync feature bitmap */
-    if (dev->vdev->get_features) {
-        stl_phys(cur_offs, dev->vdev->get_features(dev->vdev));
-    }
+    stl_phys(cur_offs, dev->host_features);
 
     dev->feat_offs = cur_offs + dev->feat_len;
     cur_offs += dev->feat_len * 2;
@@ -310,10 +309,17 @@ static void virtio_s390_notify(void *opa
     kvm_s390_virtio_irq(s390_cpu_addr2state(0), 0, token);
 }
 
+static unsigned virtio_s390_get_features(void *opaque)
+{
+    VirtIOS390Device *dev = (VirtIOS390Device*)opaque;
+    return dev->host_features;
+}
+
 /**************** S390 Virtio Bus Device Descriptions *******************/
 
 static const VirtIOBindings virtio_s390_bindings = {
     .notify = virtio_s390_notify,
+    .get_features = virtio_s390_get_features,
 };
 
 static VirtIOS390DeviceInfo s390_virtio_net = {
--- a/hw/s390-virtio-bus.h	2010-02-09 00:18:58.000000000 -0600
+++ b/s390-virtio-bus.h	2010-02-09 00:18:16.000000000 -0600
@@ -40,6 +40,7 @@ typedef struct VirtIOS390Device {
     VirtIODevice *vdev;
     DriveInfo *dinfo;
     NICConf nic;
+    uint32_t host_features;
     /* Max. number of ports we can have for a the virtio-serial device */
     uint32_t max_virtserial_ports;
 } VirtIOS390Device;
--- a/hw/syborg_virtio.c	2010-02-09 00:18:58.000000000 -0600
+++ b/hw/syborg_virtio.c	2010-02-09 00:02:12.000000000 -0600
@@ -25,6 +25,7 @@
 #include "syborg.h"
 #include "sysbus.h"
 #include "virtio.h"
+#include "virtio-net.h"
 #include "sysemu.h"
 
 //#define DEBUG_SYBORG_VIRTIO
@@ -66,6 +67,7 @@ typedef struct {
     uint32_t int_enable;
     uint32_t id;
     NICConf nic;
+    uint32_t host_features;
 } SyborgVirtIOProxy;
 
 static uint32_t syborg_virtio_readl(void *opaque, target_phys_addr_t offset)
@@ -86,8 +88,7 @@ static uint32_t syborg_virtio_readl(void
         ret = s->id;
         break;
     case SYBORG_VIRTIO_HOST_FEATURES:
-        ret = vdev->get_features(vdev);
-        ret |= vdev->binding->get_features(s);
+        ret = s->host_features;
         break;
     case SYBORG_VIRTIO_GUEST_FEATURES:
         ret = vdev->guest_features;
@@ -244,9 +245,8 @@ static void syborg_virtio_update_irq(voi
 
 static unsigned syborg_virtio_get_features(void *opaque)
 {
-    unsigned ret = 0;
-    ret |= (1 << VIRTIO_F_NOTIFY_ON_EMPTY);
-    return ret;
+    SyborgVirtIOProxy *proxy = opaque;
+    return proxy->host_features;
 }
 
 static VirtIOBindings syborg_virtio_bindings = {
@@ -272,6 +272,8 @@ static int syborg_virtio_init(SyborgVirt
     qemu_register_reset(virtio_reset, vdev);
 
     virtio_bind_device(vdev, &syborg_virtio_bindings, proxy);
+    proxy->host_features |= (0x1 << VIRTIO_F_NOTIFY_ON_EMPTY);
+    proxy->host_features = vdev->get_features(vdev, proxy->host_features);
     return 0;
 }
 
@@ -292,6 +294,7 @@ static SysBusDeviceInfo syborg_virtio_ne
     .qdev.size  = sizeof(SyborgVirtIOProxy),
     .qdev.props = (Property[]) {
         DEFINE_NIC_PROPERTIES(SyborgVirtIOProxy, nic),
+        DEFINE_VIRTIO_NET_FEATURES(SyborgVirtIOProxy, host_features),
         DEFINE_PROP_END_OF_LIST(),
     }
 };
--- a/hw/virtio-balloon.c	2010-01-18 12:48:25.000000000 -0600
+++ b/hw/virtio-balloon.c	2010-02-09 00:02:12.000000000 -0600
@@ -125,9 +125,9 @@ static void virtio_balloon_set_config(Vi
     dev->actual = config.actual;
 }
 
-static uint32_t virtio_balloon_get_features(VirtIODevice *vdev)
+static uint32_t virtio_balloon_get_features(VirtIODevice *vdev, uint32_t f)
 {
-    return 0;
+    return f;
 }
 
 static ram_addr_t virtio_balloon_to_target(void *opaque, ram_addr_t target)
--- a/hw/virtio-blk.c	2010-01-18 12:48:25.000000000 -0600
+++ b/hw/virtio-blk.c	2010-02-09 00:02:12.000000000 -0600
@@ -432,19 +432,15 @@ static void virtio_blk_update_config(Vir
     memcpy(config, &blkcfg, s->config_size);
 }
 
-static uint32_t virtio_blk_get_features(VirtIODevice *vdev)
+static uint32_t virtio_blk_get_features(VirtIODevice *vdev, uint32_t features)
 {
     VirtIOBlock *s = to_virtio_blk(vdev);
-    uint32_t features = 0;
 
     features |= (1 << VIRTIO_BLK_F_SEG_MAX);
     features |= (1 << VIRTIO_BLK_F_GEOMETRY);
 
     if (bdrv_enable_write_cache(s->bs))
         features |= (1 << VIRTIO_BLK_F_WCACHE);
-#ifdef __linux__
-    features |= (1 << VIRTIO_BLK_F_SCSI);
-#endif
     if (strcmp(s->serial_str, "0"))
         features |= 1 << VIRTIO_BLK_F_IDENTIFY;
     
--- a/hw/virtio-blk.h	2010-01-18 12:48:25.000000000 -0600
+++ b/hw/virtio-blk.h	2010-02-09 00:02:12.000000000 -0600
@@ -92,4 +92,12 @@ struct virtio_scsi_inhdr
     uint32_t residual;
 };
 
+#ifdef __linux__
+#define DEFINE_VIRTIO_BLK_FEATURES(_state, _field) \
+        DEFINE_VIRTIO_COMMON_FEATURES(_state, _field), \
+        DEFINE_PROP_BIT("scsi", _state, _field, VIRTIO_BLK_F_SCSI, true)
+#else
+#define DEFINE_VIRTIO_BLK_FEATURES(_state, _field) \
+        DEFINE_VIRTIO_COMMON_FEATURES(_state, _field)
+#endif
 #endif
--- a/hw/virtio.c	2010-02-09 00:18:58.000000000 -0600
+++ b/hw/virtio.c	2010-02-09 00:02:12.000000000 -0600
@@ -650,7 +650,7 @@ int virtio_load(VirtIODevice *vdev, QEMU
 {
     int num, i, ret;
     uint32_t features;
-    uint32_t supported_features = vdev->get_features(vdev) |
+    uint32_t supported_features =
         vdev->binding->get_features(vdev->binding_opaque);
 
     if (vdev->binding->load_config) {
--- a/hw/virtio.h	2010-02-09 00:18:58.000000000 -0600
+++ bhw/virtio.h	2010-02-09 00:02:12.000000000 -0600
@@ -105,7 +105,7 @@ struct VirtIODevice
     void *config;
     uint16_t config_vector;
     int nvectors;
-    uint32_t (*get_features)(VirtIODevice *vdev);
+    uint32_t (*get_features)(VirtIODevice *vdev, uint32_t requested_features);
     uint32_t (*bad_features)(VirtIODevice *vdev);
     void (*set_features)(VirtIODevice *vdev, uint32_t val);
     void (*get_config)(VirtIODevice *vdev, uint8_t *config);
@@ -176,4 +176,9 @@ VirtIODevice *virtio_balloon_init(Device
 
 void virtio_net_exit(VirtIODevice *vdev);
 
+#define DEFINE_VIRTIO_COMMON_FEATURES(_state, _field) \
+	DEFINE_PROP_BIT("indirect_desc", _state, _field, \
+			VIRTIO_RING_F_INDIRECT_DESC, true)
+
+
 #endif
--- a/hw/virtio-net.c	2010-02-09 00:18:58.000000000 -0600
+++ b/hw/virtio-net.c	2010-02-09 00:02:12.000000000 -0600
@@ -147,34 +147,27 @@ static int peer_has_ufo(VirtIONet *n)
     return n->has_ufo;
 }
 
-static uint32_t virtio_net_get_features(VirtIODevice *vdev)
+static uint32_t virtio_net_get_features(VirtIODevice *vdev, uint32_t features)
 {
     VirtIONet *n = to_virtio_net(vdev);
-    uint32_t features = (1 << VIRTIO_NET_F_MAC) |
-                        (1 << VIRTIO_NET_F_MRG_RXBUF) |
-                        (1 << VIRTIO_NET_F_STATUS) |
-                        (1 << VIRTIO_NET_F_CTRL_VQ) |
-                        (1 << VIRTIO_NET_F_CTRL_RX) |
-                        (1 << VIRTIO_NET_F_CTRL_VLAN) |
-                        (1 << VIRTIO_NET_F_CTRL_RX_EXTRA);
 
     if (peer_has_vnet_hdr(n)) {
         tap_using_vnet_hdr(n->nic->nc.peer, 1);
+    } else {
+        features &= ~(0x1 << VIRTIO_NET_F_CSUM);
+        features &= ~(0x1 << VIRTIO_NET_F_HOST_TSO4);
+        features &= ~(0x1 << VIRTIO_NET_F_HOST_TSO6);
+        features &= ~(0x1 << VIRTIO_NET_F_HOST_ECN);
+
+        features &= ~(0x1 << VIRTIO_NET_F_GUEST_CSUM);
+        features &= ~(0x1 << VIRTIO_NET_F_GUEST_TSO4);
+        features &= ~(0x1 << VIRTIO_NET_F_GUEST_TSO6);
+        features &= ~(0x1 << VIRTIO_NET_F_GUEST_ECN);
+    }
 
-        features |= (1 << VIRTIO_NET_F_CSUM);
-        features |= (1 << VIRTIO_NET_F_HOST_TSO4);
-        features |= (1 << VIRTIO_NET_F_HOST_TSO6);
-        features |= (1 << VIRTIO_NET_F_HOST_ECN);
-
-        features |= (1 << VIRTIO_NET_F_GUEST_CSUM);
-        features |= (1 << VIRTIO_NET_F_GUEST_TSO4);
-        features |= (1 << VIRTIO_NET_F_GUEST_TSO6);
-        features |= (1 << VIRTIO_NET_F_GUEST_ECN);
-
-        if (peer_has_ufo(n)) {
-            features |= (1 << VIRTIO_NET_F_GUEST_UFO);
-            features |= (1 << VIRTIO_NET_F_HOST_UFO);
-        }
+    if (!peer_has_vnet_hdr(n) || !peer_has_ufo(n)) {
+        features &= ~(0x1 << VIRTIO_NET_F_GUEST_UFO);
+        features &= ~(0x1 << VIRTIO_NET_F_HOST_UFO);
     }
 
     return features;
@@ -192,7 +185,7 @@ static uint32_t virtio_net_bad_features(
     features |= (1 << VIRTIO_NET_F_HOST_TSO6);
     features |= (1 << VIRTIO_NET_F_HOST_ECN);
 
-    return features & virtio_net_get_features(vdev);
+    return features;
 }
 
 static void virtio_net_set_features(VirtIODevice *vdev, uint32_t features)
--- a/hw/virtio-net.h	2010-01-18 12:48:25.000000000 -0600
+++ b/hw/virtio-net.h	2010-02-09 00:02:12.000000000 -0600
@@ -153,4 +153,24 @@ struct virtio_net_ctrl_mac {
  #define VIRTIO_NET_CTRL_VLAN_ADD             0
  #define VIRTIO_NET_CTRL_VLAN_DEL             1
 
+#define DEFINE_VIRTIO_NET_FEATURES(_state, _field) \
+        DEFINE_VIRTIO_COMMON_FEATURES(_state, _field), \
+        DEFINE_PROP_BIT("csum", _state, _field, VIRTIO_NET_F_CSUM, true), \
+        DEFINE_PROP_BIT("guest_csum", _state, _field, VIRTIO_NET_F_GUEST_CSUM, true), \
+        DEFINE_PROP_BIT("mac", _state, _field, VIRTIO_NET_F_MAC, true), \
+        DEFINE_PROP_BIT("gso", _state, _field, VIRTIO_NET_F_GSO, true), \
+        DEFINE_PROP_BIT("guest_tso4", _state, _field, VIRTIO_NET_F_GUEST_TSO4, true), \
+        DEFINE_PROP_BIT("guest_tso6", _state, _field, VIRTIO_NET_F_GUEST_TSO6, true), \
+        DEFINE_PROP_BIT("guest_ecn", _state, _field, VIRTIO_NET_F_GUEST_ECN, true), \
+        DEFINE_PROP_BIT("guest_ufo", _state, _field, VIRTIO_NET_F_GUEST_UFO, true), \
+        DEFINE_PROP_BIT("host_tso4", _state, _field, VIRTIO_NET_F_HOST_TSO4, true), \
+        DEFINE_PROP_BIT("host_tso6", _state, _field, VIRTIO_NET_F_HOST_TSO6, true), \
+        DEFINE_PROP_BIT("host_ecn", _state, _field, VIRTIO_NET_F_HOST_ECN, true), \
+        DEFINE_PROP_BIT("host_ufo", _state, _field, VIRTIO_NET_F_HOST_UFO, true), \
+        DEFINE_PROP_BIT("mrg_rxbuf", _state, _field, VIRTIO_NET_F_MRG_RXBUF, true), \
+        DEFINE_PROP_BIT("status", _state, _field, VIRTIO_NET_F_STATUS, true), \
+        DEFINE_PROP_BIT("ctrl_vq", _state, _field, VIRTIO_NET_F_CTRL_VQ, true), \
+        DEFINE_PROP_BIT("ctrl_rx", _state, _field, VIRTIO_NET_F_CTRL_RX, true), \
+        DEFINE_PROP_BIT("ctrl_vlan", _state, _field, VIRTIO_NET_F_CTRL_VLAN, true), \
+        DEFINE_PROP_BIT("ctrl_rx_extra", _state, _field, VIRTIO_NET_F_CTRL_RX_EXTRA, true)
 #endif
--- a/hw/virtio-pci.c	2010-02-09 00:18:58.000000000 -0600
+++ b/hw/virtio-pci.c	2010-02-09 00:16:13.000000000 -0600
@@ -16,6 +16,8 @@
 #include <inttypes.h>
 
 #include "virtio.h"
+#include "virtio-blk.h"
+#include "virtio-net.h"
 #include "pci.h"
 #include "sysemu.h"
 #include "msix.h"
@@ -92,6 +94,7 @@ typedef struct {
     uint32_t nvectors;
     DriveInfo *dinfo;
     NICConf nic;
+    uint32_t host_features;
     /* Max. number of ports we can have for a the virtio-serial device */
     uint32_t max_virtserial_ports;
 } VirtIOPCIProxy;
@@ -177,7 +180,7 @@ static void virtio_ioport_write(void *op
 	/* Guest does not negotiate properly?  We have to assume nothing. */
 	if (val & (1 << VIRTIO_F_BAD_FEATURE)) {
 	    if (vdev->bad_features)
-		val = vdev->bad_features(vdev);
+		val = proxy->host_features & vdev->bad_features(vdev);
 	    else
 		val = 0;
 	}
@@ -237,8 +240,7 @@ static uint32_t virtio_ioport_read(VirtI
 
     switch (addr) {
     case VIRTIO_PCI_HOST_FEATURES:
-        ret = vdev->get_features(vdev);
-        ret |= vdev->binding->get_features(proxy);
+        ret = proxy->host_features;
         break;
     case VIRTIO_PCI_GUEST_FEATURES:
         ret = vdev->guest_features;
@@ -384,11 +386,8 @@ static void virtio_write_config(PCIDevic
 
 static unsigned virtio_pci_get_features(void *opaque)
 {
-    unsigned ret = 0;
-    ret |= (1 << VIRTIO_F_NOTIFY_ON_EMPTY);
-    ret |= (1 << VIRTIO_RING_F_INDIRECT_DESC);
-    ret |= (1 << VIRTIO_F_BAD_FEATURE);
-    return ret;
+    VirtIOPCIProxy *proxy = opaque;
+    return proxy->host_features;
 }
 
 static const VirtIOBindings virtio_pci_bindings = {
@@ -444,6 +443,9 @@ static void virtio_init_pci(VirtIOPCIPro
                            virtio_map);
 
     virtio_bind_device(vdev, &virtio_pci_bindings, proxy);
+    proxy->host_features |= 0x1 << VIRTIO_F_NOTIFY_ON_EMPTY;
+    proxy->host_features |= 0x1 << VIRTIO_F_BAD_FEATURE;
+    proxy->host_features = vdev->get_features(vdev, proxy->host_features);
 }
 
 static int virtio_blk_init_pci(PCIDevice *pci_dev)
@@ -558,6 +560,7 @@ static PCIDeviceInfo virtio_info[] = {
             DEFINE_PROP_HEX32("class", VirtIOPCIProxy, class_code, 0),
             DEFINE_PROP_DRIVE("drive", VirtIOPCIProxy, dinfo),
             DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 2),
+            DEFINE_VIRTIO_BLK_FEATURES(VirtIOPCIProxy, host_features),
             DEFINE_PROP_END_OF_LIST(),
         },
         .qdev.reset = virtio_pci_reset,
@@ -569,6 +572,7 @@ static PCIDeviceInfo virtio_info[] = {
         .romfile    = "pxe-virtio.bin",
         .qdev.props = (Property[]) {
             DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 3),
+            DEFINE_VIRTIO_NET_FEATURES(VirtIOPCIProxy, host_features),
             DEFINE_NIC_PROPERTIES(VirtIOPCIProxy, nic),
             DEFINE_PROP_END_OF_LIST(),
         },
@@ -582,6 +586,7 @@ static PCIDeviceInfo virtio_info[] = {
         .qdev.props = (Property[]) {
             DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 0),
             DEFINE_PROP_HEX32("class", VirtIOPCIProxy, class_code, 0),
+            DEFINE_VIRTIO_COMMON_FEATURES(VirtIOPCIProxy, host_features),
             DEFINE_PROP_UINT32("max_ports", VirtIOPCIProxy, max_virtserial_ports,
                                31),
             DEFINE_PROP_END_OF_LIST(),
@@ -592,6 +597,10 @@ static PCIDeviceInfo virtio_info[] = {
         .qdev.size = sizeof(VirtIOPCIProxy),
         .init      = virtio_balloon_init_pci,
         .exit      = virtio_exit_pci,
+        .qdev.props = (Property[]) {
+            DEFINE_VIRTIO_COMMON_FEATURES(VirtIOPCIProxy, host_features),
+            DEFINE_PROP_END_OF_LIST(),
+        },
         .qdev.reset = virtio_pci_reset,
     },{
         /* end of list */

qemu-virtio-add-notifier-support.patch:
 virtio.c |   13 ++++++++++---
 virtio.h |    6 ++++--
 2 files changed, 14 insertions(+), 5 deletions(-)

--- NEW FILE qemu-virtio-add-notifier-support.patch ---
Add binding API to set host/guest notifiers.
Will be used by vhost.

Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
---
 hw/virtio.c |   13 ++++++++++---
 hw/virtio.h |    5 ++++-
 2 files changed, 14 insertions(+), 4 deletions(-)

diff --git a/hw/virtio.c b/hw/virtio.c
index fa7184a..c2b80aa 100644
--- a/hw/virtio.c
+++ b/hw/virtio.c
@@ -594,6 +594,12 @@ VirtQueue *virtio_add_queue(VirtIODevice *vdev, int queue_size,
     return &vdev->vq[i];
 }
 
+void virtio_irq(VirtIODevice *vdev, VirtQueue *vq)
+{
+    vdev->isr |= 0x01;
+    virtio_notify_vector(vdev, vq->vector);
+}
+
 void virtio_notify(VirtIODevice *vdev, VirtQueue *vq)
 {
     /* Always notify when queue is empty (when feature acknowledge) */
@@ -602,8 +608,7 @@ void virtio_notify(VirtIODevice *vdev, VirtQueue *vq)
          (vq->inuse || vring_avail_idx(vq) != vq->last_avail_idx)))
         return;
 
-    vdev->isr |= 0x01;
-    virtio_notify_vector(vdev, vq->vector);
+    virtio_irq(vdev, vq);
 }
 
 void virtio_notify_config(VirtIODevice *vdev)
@@ -716,8 +721,10 @@ VirtIODevice *virtio_common_init(const char *name, uint16_t device_id,
     vdev->queue_sel = 0;
     vdev->config_vector = VIRTIO_NO_VECTOR;
     vdev->vq = qemu_mallocz(sizeof(VirtQueue) * VIRTIO_PCI_QUEUE_MAX);
-    for(i = 0; i < VIRTIO_PCI_QUEUE_MAX; i++)
+    for(i = 0; i < VIRTIO_PCI_QUEUE_MAX; i++) {
         vdev->vq[i].vector = VIRTIO_NO_VECTOR;
+        vdev->vq[i].vdev = vdev;
+    }
 
     vdev->name = name;
     vdev->config_len = config_size;
diff --git a/hw/virtio.h b/hw/virtio.h
index 3994cc9..10a0959 100644
--- a/hw/virtio.h
+++ b/hw/virtio.h
@@ -18,6 +18,7 @@
 #include "net.h"
 #include "qdev.h"
 #include "sysemu.h"
+#include "notifier.h"
 
 /* from Linux's linux/virtio_config.h */
 
@@ -88,6 +89,8 @@ typedef struct {
     int (*load_config)(void * opaque, QEMUFile *f);
     int (*load_queue)(void * opaque, int n, QEMUFile *f);
     unsigned (*get_features)(void * opaque);
+    int (*guest_notifier)(void * opaque, int n, bool assigned);
+    int (*host_notifier)(void * opaque, int n, bool assigned);
 } VirtIOBindings;
 
 #define VIRTIO_PCI_QUEUE_MAX 64
@@ -180,5 +183,5 @@ void virtio_net_exit(VirtIODevice *vdev);
 	DEFINE_PROP_BIT("indirect_desc", _state, _field, \
 			VIRTIO_RING_F_INDIRECT_DESC, true)
 
-
+void virtio_irq(VirtIODevice *vdev, VirtQueue *vq);
 #endif
-- 
1.6.6.144.g5c3af

qemu-virtio-add-status-change-callback.patch:
 s390-virtio-bus.c |    3 +++
 syborg_virtio.c   |    2 ++
 virtio-pci.c      |    6 ++++++
 virtio.h          |    2 +-
 4 files changed, 12 insertions(+), 1 deletion(-)

--- NEW FILE qemu-virtio-add-status-change-callback.patch ---
vhost net backend needs to be notified when
frontend status changes. Add a callback.

Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
---
 hw/s390-virtio-bus.c |    3 +++
 hw/syborg_virtio.c   |    2 ++
 hw/virtio-pci.c      |    6 ++++++
 hw/virtio.h          |    1 +
 4 files changed, 12 insertions(+), 0 deletions(-)

diff --git a/hw/s390-virtio-bus.c b/hw/s390-virtio-bus.c
index 980e7eb..f45b67d 100644
--- a/hw/s390-virtio-bus.c
+++ b/hw/s390-virtio-bus.c
@@ -243,6 +243,9 @@ void s390_virtio_device_update_status(VirtIOS390Device *dev)
     uint32_t features;
 
     vdev->status = ldub_phys(dev->dev_offs + VIRTIO_DEV_OFFS_STATUS);
+    if (vdev->set_status) {
+        vdev->set_status(vdev);
+    }
 
     /* Update guest supported feature bitmap */
 
diff --git a/hw/syborg_virtio.c b/hw/syborg_virtio.c
index 65239a0..19f6473 100644
--- a/hw/syborg_virtio.c
+++ b/hw/syborg_virtio.c
@@ -152,6 +152,8 @@ static void syborg_virtio_writel(void *opaque, target_phys_addr_t offset,
         vdev->status = value & 0xFF;
         if (vdev->status == 0)
             virtio_reset(vdev);
+        if (vdev->set_status)
+            vdev->set_status(vdev);
         break;
     case SYBORG_VIRTIO_INT_ENABLE:
         s->int_enable = value;
diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c
index 573c98a..05898c8 100644
--- a/hw/virtio-pci.c
+++ b/hw/virtio-pci.c
@@ -208,6 +208,9 @@ static void virtio_ioport_write(void *opaque, uint32_t addr, uint32_t val)
             virtio_reset(proxy->vdev);
             msix_unuse_all_vectors(&proxy->pci_dev);
         }
+        if (vdev->set_status) {
+            vdev->set_status(vdev);
+        }
         break;
     case VIRTIO_MSI_CONFIG_VECTOR:
         msix_vector_unuse(&proxy->pci_dev, vdev->config_vector);
@@ -375,6 +378,9 @@ static void virtio_write_config(PCIDevice *pci_dev, uint32_t address,
     if (PCI_COMMAND == address) {
         if (!(val & PCI_COMMAND_MASTER)) {
             proxy->vdev->status &= ~VIRTIO_CONFIG_S_DRIVER_OK;
+            if (proxy->vdev->set_status) {
+                proxy->vdev->set_status(proxy->vdev);
+            }
         }
     }
 
diff --git a/hw/virtio.h b/hw/virtio.h
index f140ca3..39d0763 100644
--- a/hw/virtio.h
+++ b/hw/virtio.h
@@ -114,6 +114,7 @@ struct VirtIODevice
     void (*get_config)(VirtIODevice *vdev, uint8_t *config);
     void (*set_config)(VirtIODevice *vdev, const uint8_t *config);
     void (*reset)(VirtIODevice *vdev);
+    void (*set_status)(VirtIODevice *vdev);
     VirtQueue *vq;
     const VirtIOBindings *binding;
     void *binding_opaque;
-- 
1.6.6.144.g5c3af

qemu-virtio-avoid-crash-with-non-tap-backends.patch:
 virtio-net.c |    5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

--- NEW FILE qemu-virtio-avoid-crash-with-non-tap-backends.patch ---
verify that peer is tap before checking for vhost net

Reported-by: Shirley Ma <mashirle at us.ibm.com>
Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
---
 hw/virtio-net.c |    4 ++++
 1 files changed, 4 insertions(+), 0 deletions(-)

diff --git a/hw/virtio-net.c b/hw/virtio-net.c
index 088029b..b28fd92 100644
--- a/hw/virtio-net.c
+++ b/hw/virtio-net.c
@@ -179,6 +179,10 @@ static uint32_t virtio_net_get_features(VirtIODevice *vdev, uint32_t features)
         features &= ~(0x1 << VIRTIO_NET_F_HOST_UFO);
     }
 
+    if (!n->nic->nc.peer ||
+	n->nic->nc.peer->info->type != NET_CLIENT_TYPE_TAP) {
+        return features;
+    }
     if (!tap_get_vhost_net(n->nic->nc.peer)) {
         return features;
     }
-- 
1.6.6.144.g5c3af

qemu-virtio-move-typedef-to-qemu-common.patch:
 hw/virtio.h   |    1 -
 qemu-common.h |    2 +-
 2 files changed, 1 insertion(+), 2 deletions(-)

--- NEW FILE qemu-virtio-move-typedef-to-qemu-common.patch ---
make it possible to use type without header include

Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
---
 hw/virtio.h   |    1 -
 qemu-common.h |    1 +
 2 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/hw/virtio.h b/hw/virtio.h
index 39d0763..a5bd0ba 100644
--- a/hw/virtio.h
+++ b/hw/virtio.h
@@ -68,7 +68,6 @@ static inline target_phys_addr_t vring_align(target_phys_addr_t addr,
 }
 
 typedef struct VirtQueue VirtQueue;
-typedef struct VirtIODevice VirtIODevice;
 
 #define VIRTQUEUE_MAX_SIZE 1024
 
diff --git a/qemu-common.h b/qemu-common.h
index cdead98..1a54f9e 100644
--- a/qemu-common.h
+++ b/qemu-common.h
@@ -218,6 +218,7 @@ typedef struct I2SCodec I2SCodec;
 typedef struct DeviceState DeviceState;
 typedef struct SSIBus SSIBus;
 typedef struct EventNotifier EventNotifier;
+typedef struct VirtIODevice VirtIODevice;
 
 /* CPU save/load.  */
 void cpu_save(QEMUFile *f, void *opaque);
-- 
1.6.6.144.g5c3af

qemu-virtio-net-mac-property-is-mandatory.patch:
 virtio-net.c |    2 ++
 virtio-net.h |    2 --
 2 files changed, 2 insertions(+), 2 deletions(-)

--- NEW FILE qemu-virtio-net-mac-property-is-mandatory.patch ---
Mac feature bit isn't going to work as all network cards already have a
'mac' property to set the mac address.  Remove it from mask and add in
get_features.

Reported-by: Gerd Hoffmann <kraxel at redhat.com>
Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
(cherry picked from commit c9f79a3f79a48de28b4575cb5644bcf45d3754d0)
---
 hw/virtio-net.c |    2 ++
 hw/virtio-net.h |    1 -
 2 files changed, 2 insertions(+), 1 deletions(-)

diff --git a/hw/virtio-net.c b/hw/virtio-net.c
index c2a389f..02d9180 100644
--- a/hw/virtio-net.c
+++ b/hw/virtio-net.c
@@ -151,6 +151,8 @@ static uint32_t virtio_net_get_features(VirtIODevice *vdev, uint32_t features)
 {
     VirtIONet *n = to_virtio_net(vdev);
 
+    features |= (1 << VIRTIO_NET_F_MAC);
+
     if (peer_has_vnet_hdr(n)) {
         tap_using_vnet_hdr(n->nic->nc.peer, 1);
     } else {
diff --git a/hw/virtio-net.h b/hw/virtio-net.h
index 9130d75..e55119b 100644
--- a/hw/virtio-net.h
+++ b/hw/virtio-net.h
@@ -157,7 +157,6 @@ struct virtio_net_ctrl_mac {
         DEFINE_VIRTIO_COMMON_FEATURES(_state, _field), \
         DEFINE_PROP_BIT("csum", _state, _field, VIRTIO_NET_F_CSUM, true), \
         DEFINE_PROP_BIT("guest_csum", _state, _field, VIRTIO_NET_F_GUEST_CSUM, true), \
-        DEFINE_PROP_BIT("mac", _state, _field, VIRTIO_NET_F_MAC, true), \
         DEFINE_PROP_BIT("gso", _state, _field, VIRTIO_NET_F_GSO, true), \
         DEFINE_PROP_BIT("guest_tso4", _state, _field, VIRTIO_NET_F_GUEST_TSO4, true), \
         DEFINE_PROP_BIT("guest_tso6", _state, _field, VIRTIO_NET_F_GUEST_TSO6, true), \
-- 
1.6.6.144.g5c3af

qemu-virtio-net-vhost-net-support.patch:
 virtio-net.c |   68 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 65 insertions(+), 3 deletions(-)

--- NEW FILE qemu-virtio-net-vhost-net-support.patch ---
This connects virtio-net to vhost net backend.
The code is structured in a way analogous to what we have with vnet
header capability in tap.  We start/stop backend on driver start/stop as
well as on save and vm start (for migration).

Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
---
 hw/virtio-net.c |   67 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 65 insertions(+), 2 deletions(-)

diff --git a/hw/virtio-net.c b/hw/virtio-net.c
index 02d9180..088029b 100644
--- a/hw/virtio-net.c
+++ b/hw/virtio-net.c
@@ -17,6 +17,7 @@
 #include "net/tap.h"
 #include "qemu-timer.h"
 #include "virtio-net.h"
+#include "vhost_net.h"
 
 #define VIRTIO_NET_VM_VERSION    11
 
@@ -47,6 +48,8 @@ typedef struct VirtIONet
     uint8_t nomulti;
     uint8_t nouni;
     uint8_t nobcast;
+    uint8_t vhost_started;
+    VMChangeStateEntry *vmstate;
     struct {
         int in_use;
         int first_multi;
@@ -114,6 +117,10 @@ static void virtio_net_reset(VirtIODevice *vdev)
     n->nomulti = 0;
     n->nouni = 0;
     n->nobcast = 0;
+    if (n->vhost_started) {
+        vhost_net_stop(tap_get_vhost_net(n->nic->nc.peer), vdev);
+        n->vhost_started = 0;
+    }
 
     /* Flush any MAC and VLAN filter table state */
     n->mac_table.in_use = 0;
@@ -172,7 +179,10 @@ static uint32_t virtio_net_get_features(VirtIODevice *vdev, uint32_t features)
         features &= ~(0x1 << VIRTIO_NET_F_HOST_UFO);
     }
 
-    return features;
+    if (!tap_get_vhost_net(n->nic->nc.peer)) {
+        return features;
+    }
+    return vhost_net_get_features(tap_get_vhost_net(n->nic->nc.peer), features);
 }
 
 static uint32_t virtio_net_bad_features(VirtIODevice *vdev)
@@ -690,6 +700,12 @@ static void virtio_net_save(QEMUFile *f, void *opaque)
 {
     VirtIONet *n = opaque;
 
+    if (n->vhost_started) {
+	/* TODO: should we really stop the backend?
+	 * If we don't, it might keep writing to memory. */
+        vhost_net_stop(tap_get_vhost_net(n->nic->nc.peer), &n->vdev);
+	n->vhost_started = 0;
+    }
     virtio_save(&n->vdev, f);
 
     qemu_put_buffer(f, n->mac, ETH_ALEN);
@@ -802,7 +818,6 @@ static int virtio_net_load(QEMUFile *f, void *opaque, int version_id)
         qemu_mod_timer(n->tx_timer,
                        qemu_get_clock(vm_clock) + TX_TIMER_INTERVAL);
     }
-
     return 0;
 }
 
@@ -822,6 +837,47 @@ static NetClientInfo net_virtio_info = {
     .link_status_changed = virtio_net_set_link_status,
 };
 
+static void virtio_net_set_status(struct VirtIODevice *vdev)
+{
+    VirtIONet *n = to_virtio_net(vdev);
+    if (!n->nic->nc.peer) {
+        return;
+    }
+    if (n->nic->nc.peer->info->type != NET_CLIENT_TYPE_TAP) {
+        return;
+    }
+
+    if (!tap_get_vhost_net(n->nic->nc.peer)) {
+        return;
+    }
+    if (!!n->vhost_started == !!(vdev->status & VIRTIO_CONFIG_S_DRIVER_OK)) {
+        return;
+    }
+    if (vdev->status & VIRTIO_CONFIG_S_DRIVER_OK) {
+        int r = vhost_net_start(tap_get_vhost_net(n->nic->nc.peer), vdev);
+        if (r < 0) {
+            fprintf(stderr, "unable to start vhost net: %d: "
+                    "falling back on userspace virtio\n", -r);
+        } else {
+            n->vhost_started = 1;
+        }
+    } else {
+        vhost_net_stop(tap_get_vhost_net(n->nic->nc.peer), vdev);
+        n->vhost_started = 0;
+    }
+}
+
+static void virtio_net_vmstate_change(void *opaque, int running, int reason)
+{
+	VirtIONet *n = opaque;
+	if (!running) {
+		return;
+	}
+	/* This is called when vm is started, it will start vhost backend if it
+	 * appropriate e.g. after migration. */
+	virtio_net_set_status(&n->vdev);
+}
+
 VirtIODevice *virtio_net_init(DeviceState *dev, NICConf *conf)
 {
     VirtIONet *n;
@@ -837,6 +893,7 @@ VirtIODevice *virtio_net_init(DeviceState *dev, NICConf *conf)
     n->vdev.set_features = virtio_net_set_features;
     n->vdev.bad_features = virtio_net_bad_features;
     n->vdev.reset = virtio_net_reset;
+    n->vdev.set_status = virtio_net_set_status;
     n->rx_vq = virtio_add_queue(&n->vdev, 256, virtio_net_handle_rx);
     n->tx_vq = virtio_add_queue(&n->vdev, 256, virtio_net_handle_tx);
     n->ctrl_vq = virtio_add_queue(&n->vdev, 64, virtio_net_handle_ctrl);
@@ -859,6 +916,7 @@ VirtIODevice *virtio_net_init(DeviceState *dev, NICConf *conf)
 
     register_savevm("virtio-net", virtio_net_id++, VIRTIO_NET_VM_VERSION,
                     virtio_net_save, virtio_net_load, n);
+    n->vmstate = qemu_add_vm_change_state_handler(virtio_net_vmstate_change, n);
 
     return &n->vdev;
 }
@@ -866,6 +924,11 @@ VirtIODevice *virtio_net_init(DeviceState *dev, NICConf *conf)
 void virtio_net_exit(VirtIODevice *vdev)
 {
     VirtIONet *n = DO_UPCAST(VirtIONet, vdev, vdev);
+    qemu_del_vm_change_state_handler(n->vmstate);
+
+    if (n->vhost_started) {
+        vhost_net_stop(tap_get_vhost_net(n->nic->nc.peer), vdev);
+    }
 
     qemu_purge_queued_packets(&n->nic->nc);
 
-- 
1.6.6.144.g5c3af

qemu-virtio-pci-fill-in-notifier-support.patch:
 virtio-pci.c |   63 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 62 insertions(+), 1 deletion(-)

--- NEW FILE qemu-virtio-pci-fill-in-notifier-support.patch ---
Support host/guest notifiers in virtio-pci.
The last one only with kvm, that's okay
because vhost relies on kvm anyway.

Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
---
 hw/virtio-pci.c |   62 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 62 insertions(+), 0 deletions(-)

diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c
index 05898c8..c454093 100644
--- a/hw/virtio-pci.c
+++ b/hw/virtio-pci.c
@@ -23,6 +23,7 @@
 #include "msix.h"
 #include "net.h"
 #include "loader.h"
+#include "kvm.h"
 
 /* from Linux's linux/virtio_pci.h */
 
@@ -394,6 +395,65 @@ static unsigned virtio_pci_get_features(void *opaque)
     return proxy->host_features;
 }
 
+static void virtio_pci_guest_notifier_read(void *opaque)
+{
+    VirtQueue *vq = opaque;
+    EventNotifier *n = virtio_queue_guest_notifier(vq);
+    if (event_notifier_test_and_clear(n)) {
+        virtio_irq(vq);
+    }
+}
+
+static int virtio_pci_guest_notifier(void *opaque, int n, bool assign)
+{
+    VirtIOPCIProxy *proxy = opaque;
+    VirtQueue *vq = virtio_queue(proxy->vdev, n);
+    EventNotifier *notifier = virtio_queue_guest_notifier(vq);
+
+    if (assign) {
+        int r = event_notifier_init(notifier, 0);
+	if (r < 0)
+		return r;
+        qemu_set_fd_handler(event_notifier_get_fd(notifier),
+                            virtio_pci_guest_notifier_read, NULL, vq);
+    } else {
+        qemu_set_fd_handler(event_notifier_get_fd(notifier),
+                            NULL, NULL, vq);
+        event_notifier_cleanup(notifier);
+    }
+
+    return 0;
+}
+
+static int virtio_pci_host_notifier(void *opaque, int n, bool assign)
+{
+    VirtIOPCIProxy *proxy = opaque;
+    VirtQueue *vq = virtio_queue(proxy->vdev, n);
+    EventNotifier *notifier = virtio_queue_host_notifier(vq);
+    int r;
+    if (assign) {
+	r = event_notifier_init(notifier, 1);
+	if (r < 0) {
+		return r;
+        }
+        r = kvm_set_ioeventfd(proxy->addr + VIRTIO_PCI_QUEUE_NOTIFY,
+                              n, event_notifier_get_fd(notifier),
+                              assign);
+        if (r < 0) {
+            event_notifier_cleanup(notifier);
+        }
+    } else {
+        r = kvm_set_ioeventfd(proxy->addr + VIRTIO_PCI_QUEUE_NOTIFY,
+                              n, event_notifier_get_fd(notifier),
+                              assign);
+	if (r < 0) {
+		return r;
+        }
+        event_notifier_cleanup(notifier);
+    }
+    return r;
+}
+
 static const VirtIOBindings virtio_pci_bindings = {
     .notify = virtio_pci_notify,
     .save_config = virtio_pci_save_config,
@@ -401,6 +461,8 @@ static const VirtIOBindings virtio_pci_bindings = {
     .save_queue = virtio_pci_save_queue,
     .load_queue = virtio_pci_load_queue,
     .get_features = virtio_pci_get_features,
+    .host_notifier = virtio_pci_host_notifier,
+    .guest_notifier = virtio_pci_guest_notifier,
 };
 
 static void virtio_init_pci(VirtIOPCIProxy *proxy, VirtIODevice *vdev,
-- 
1.6.6.144.g5c3af

qemu-virtio-pci-irqfd-fix-nonkvm-build.patch:
 virtio-pci.c |    4 ++++
 1 file changed, 4 insertions(+)

--- NEW FILE qemu-virtio-pci-irqfd-fix-nonkvm-build.patch ---
Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

---

diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c
index e8e0d82..fd0c73f 100644
--- a/hw/virtio-pci.c
+++ b/hw/virtio-pci.c
@@ -404,6 +404,7 @@ static void virtio_pci_guest_notifier_read(void *opaque)
     }
 }
 
+#ifdef CONFIG_KVM
 static int virtio_pci_mask_notifier(PCIDevice *dev, unsigned vector,
                                     void *opaque, int masked)
 {
@@ -424,6 +425,7 @@ static int virtio_pci_mask_notifier(PCIDevice *dev, unsigned vector,
     }
     return 0;
 }
+#endif
 
 static int virtio_pci_guest_notifier(void *opaque, int n, bool assign)
 {
@@ -526,7 +528,9 @@ static void virtio_init_pci(VirtIOPCIProxy *proxy, VirtIODevice *vdev,
 
     proxy->pci_dev.config_write = virtio_write_config;
 
+#ifdef CONFIG_KVM
     proxy->pci_dev.msix_mask_notifier = virtio_pci_mask_notifier;
+#endif
 
     size = VIRTIO_PCI_REGION_SIZE(&proxy->pci_dev) + vdev->config_len;
     if (size & (size-1))

qemu-virtio-pci-irqfd-support.patch:
 virtio-pci.c |   32 +++++++++++++++++++++++++++++---
 1 file changed, 29 insertions(+), 3 deletions(-)

--- NEW FILE qemu-virtio-pci-irqfd-support.patch ---
Use irqfd when supported by kernel.
This uses msix mask notifiers: when vector is masked, we poll it from
userspace.  When it is unmasked, we poll it from kernel.

Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
---
 hw/virtio-pci.c |   31 +++++++++++++++++++++++++++++--
 1 files changed, 29 insertions(+), 2 deletions(-)

diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c
index c454093..e8e0d82 100644
--- a/hw/virtio-pci.c
+++ b/hw/virtio-pci.c
@@ -404,6 +404,27 @@ static void virtio_pci_guest_notifier_read(void *opaque)
     }
 }
 
+static int virtio_pci_mask_notifier(PCIDevice *dev, unsigned vector,
+                                    void *opaque, int masked)
+{
+    VirtQueue *vq = opaque;
+    EventNotifier *notifier = virtio_queue_guest_notifier(vq);
+    int r = kvm_set_irqfd(dev->msix_irq_entries[vector].gsi,
+                          event_notifier_get_fd(notifier),
+                          !masked);
+    if (r < 0) {
+        return (r == -ENOSYS) ? 0 : r;
+    }
+    if (masked) {
+        qemu_set_fd_handler(event_notifier_get_fd(notifier),
+                            virtio_pci_guest_notifier_read, NULL, vq);
+    } else {
+        qemu_set_fd_handler(event_notifier_get_fd(notifier),
+                            NULL, NULL, vq);
+    }
+    return 0;
+}
+
 static int virtio_pci_guest_notifier(void *opaque, int n, bool assign)
 {
     VirtIOPCIProxy *proxy = opaque;
@@ -412,11 +433,15 @@ static int virtio_pci_guest_notifier(void *opaque, int n, bool assign)
 
     if (assign) {
         int r = event_notifier_init(notifier, 0);
-	if (r < 0)
-		return r;
+        if (r < 0)
+            return r;
         qemu_set_fd_handler(event_notifier_get_fd(notifier),
                             virtio_pci_guest_notifier_read, NULL, vq);
+        msix_set_mask_notifier(&proxy->pci_dev,
+			       virtio_queue_vector(proxy->vdev, n), vq);
     } else {
+        msix_set_mask_notifier(&proxy->pci_dev,
+			       virtio_queue_vector(proxy->vdev, n), NULL);
         qemu_set_fd_handler(event_notifier_get_fd(notifier),
                             NULL, NULL, vq);
         event_notifier_cleanup(notifier);
@@ -501,6 +526,8 @@ static void virtio_init_pci(VirtIOPCIProxy *proxy, VirtIODevice *vdev,
 
     proxy->pci_dev.config_write = virtio_write_config;
 
+    proxy->pci_dev.msix_mask_notifier = virtio_pci_mask_notifier;
+
     size = VIRTIO_PCI_REGION_SIZE(&proxy->pci_dev) + vdev->config_len;
     if (size & (size-1))
         size = 1 << qemu_fls(size);
-- 
1.6.6.144.g5c3af

qemu-virtio-rename-features-guest_features.patch:
 s390-virtio-bus.c |    2 +-
 syborg_virtio.c   |    4 ++--
 virtio-net.c      |   10 +++++-----
 virtio-pci.c      |    4 ++--
 virtio.c          |    8 ++++----
 virtio.h          |    3 +--
 6 files changed, 15 insertions(+), 16 deletions(-)

--- NEW FILE qemu-virtio-rename-features-guest_features.patch ---
Rename features->guest_features. This is
what they are, avoid confusion with
host features which we also need to keep around.

Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
(cherry picked from commit 704a76fcd24372a683652651b4597f6654084975)
---
 hw/s390-virtio-bus.c |    2 +-
 hw/syborg_virtio.c   |    4 ++--
 hw/virtio-net.c      |   10 +++++-----
 hw/virtio-pci.c      |    4 ++--
 hw/virtio.c          |    8 ++++----
 hw/virtio.h          |    2 +-
 6 files changed, 15 insertions(+), 15 deletions(-)

diff --git a/hw/s390-virtio-bus.c b/hw/s390-virtio-bus.c
index dc154ed..6c0da11 100644
--- a/hw/s390-virtio-bus.c
+++ b/hw/s390-virtio-bus.c
@@ -251,7 +251,7 @@ void s390_virtio_device_update_status(VirtIOS390Device *dev)
     if (vdev->set_features) {
         vdev->set_features(vdev, features);
     }
-    vdev->features = features;
+    vdev->guest_features = features;
 }
 
 VirtIOS390Device *s390_virtio_bus_console(VirtIOS390Bus *bus)
diff --git a/hw/syborg_virtio.c b/hw/syborg_virtio.c
index a84206a..fe6fc23 100644
--- a/hw/syborg_virtio.c
+++ b/hw/syborg_virtio.c
@@ -90,7 +90,7 @@ static uint32_t syborg_virtio_readl(void *opaque, target_phys_addr_t offset)
         ret |= vdev->binding->get_features(s);
         break;
     case SYBORG_VIRTIO_GUEST_FEATURES:
-        ret = vdev->features;
+        ret = vdev->guest_features;
         break;
     case SYBORG_VIRTIO_QUEUE_BASE:
         ret = virtio_queue_get_addr(vdev, vdev->queue_sel);
@@ -132,7 +132,7 @@ static void syborg_virtio_writel(void *opaque, target_phys_addr_t offset,
     case SYBORG_VIRTIO_GUEST_FEATURES:
         if (vdev->set_features)
             vdev->set_features(vdev, value);
-        vdev->features = value;
+        vdev->guest_features = value;
         break;
     case SYBORG_VIRTIO_QUEUE_BASE:
         if (value == 0)
diff --git a/hw/virtio-net.c b/hw/virtio-net.c
index 2f201ff..ab20a33 100644
--- a/hw/virtio-net.c
+++ b/hw/virtio-net.c
@@ -768,11 +768,11 @@ static int virtio_net_load(QEMUFile *f, void *opaque, int version_id)
         if (n->has_vnet_hdr) {
             tap_using_vnet_hdr(n->nic->nc.peer, 1);
             tap_set_offload(n->nic->nc.peer,
-                            (n->vdev.features >> VIRTIO_NET_F_GUEST_CSUM) & 1,
-                            (n->vdev.features >> VIRTIO_NET_F_GUEST_TSO4) & 1,
-                            (n->vdev.features >> VIRTIO_NET_F_GUEST_TSO6) & 1,
-                            (n->vdev.features >> VIRTIO_NET_F_GUEST_ECN)  & 1,
-                            (n->vdev.features >> VIRTIO_NET_F_GUEST_UFO)  & 1);
+                    (n->vdev.guest_features >> VIRTIO_NET_F_GUEST_CSUM) & 1,
+                    (n->vdev.guest_features >> VIRTIO_NET_F_GUEST_TSO4) & 1,
+                    (n->vdev.guest_features >> VIRTIO_NET_F_GUEST_TSO6) & 1,
+                    (n->vdev.guest_features >> VIRTIO_NET_F_GUEST_ECN)  & 1,
+                    (n->vdev.guest_features >> VIRTIO_NET_F_GUEST_UFO)  & 1);
         }
     }
 
diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c
index 3594152..c23dbc0 100644
--- a/hw/virtio-pci.c
+++ b/hw/virtio-pci.c
@@ -181,7 +181,7 @@ static void virtio_ioport_write(void *opaque, uint32_t addr, uint32_t val)
 	}
         if (vdev->set_features)
             vdev->set_features(vdev, val);
-        vdev->features = val;
+        vdev->guest_features = val;
         break;
     case VIRTIO_PCI_QUEUE_PFN:
         pa = (target_phys_addr_t)val << VIRTIO_PCI_QUEUE_ADDR_SHIFT;
@@ -239,7 +239,7 @@ static uint32_t virtio_ioport_read(VirtIOPCIProxy *proxy, uint32_t addr)
         ret |= vdev->binding->get_features(proxy);
         break;
     case VIRTIO_PCI_GUEST_FEATURES:
-        ret = vdev->features;
+        ret = vdev->guest_features;
         break;
     case VIRTIO_PCI_QUEUE_PFN:
         ret = virtio_queue_get_addr(vdev, vdev->queue_sel)
diff --git a/hw/virtio.c b/hw/virtio.c
index cecd0dc..c25a5f1 100644
--- a/hw/virtio.c
+++ b/hw/virtio.c
@@ -445,7 +445,7 @@ void virtio_reset(void *opaque)
     if (vdev->reset)
         vdev->reset(vdev);
 
-    vdev->features = 0;
+    vdev->guest_features = 0;
     vdev->queue_sel = 0;
     vdev->status = 0;
     vdev->isr = 0;
@@ -598,7 +598,7 @@ void virtio_notify(VirtIODevice *vdev, VirtQueue *vq)
 {
     /* Always notify when queue is empty (when feature acknowledge) */
     if ((vring_avail_flags(vq) & VRING_AVAIL_F_NO_INTERRUPT) &&
-        (!(vdev->features & (1 << VIRTIO_F_NOTIFY_ON_EMPTY)) ||
+        (!(vdev->guest_features & (1 << VIRTIO_F_NOTIFY_ON_EMPTY)) ||
          (vq->inuse || vring_avail_idx(vq) != vq->last_avail_idx)))
         return;
 
@@ -625,7 +625,7 @@ void virtio_save(VirtIODevice *vdev, QEMUFile *f)
     qemu_put_8s(f, &vdev->status);
     qemu_put_8s(f, &vdev->isr);
     qemu_put_be16s(f, &vdev->queue_sel);
-    qemu_put_be32s(f, &vdev->features);
+    qemu_put_be32s(f, &vdev->guest_features);
     qemu_put_be32(f, vdev->config_len);
     qemu_put_buffer(f, vdev->config, vdev->config_len);
 
@@ -670,7 +670,7 @@ int virtio_load(VirtIODevice *vdev, QEMUFile *f)
                 features, supported_features);
         return -1;
     }
-    vdev->features = features;
+    vdev->guest_features = features;
     vdev->config_len = qemu_get_be32(f);
     qemu_get_buffer(f, vdev->config, vdev->config_len);
 
diff --git a/hw/virtio.h b/hw/virtio.h
index 35532a6..85ef171 100644
--- a/hw/virtio.h
+++ b/hw/virtio.h
@@ -100,7 +100,7 @@ struct VirtIODevice
     uint8_t status;
     uint8_t isr;
     uint16_t queue_sel;
-    uint32_t features;
+    uint32_t guest_features;
     size_t config_len;
     void *config;
     uint16_t config_vector;
-- 
1.6.6.144.g5c3af

qemu-virtio-serial-features-build-fix.patch:
 virtio-serial-bus.c |    8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

--- NEW FILE qemu-virtio-serial-features-build-fix.patch ---
--- a/hw/virtio-serial-bus.c	2010-02-09 00:41:21.000000000 -0600
+++ b/hw/virtio-serial-bus.c	2010-02-09 00:07:13.000000000 -0600
@@ -68,7 +68,7 @@ static VirtIOSerialPort *find_port_by_vq
 
 static bool use_multiport(VirtIOSerial *vser)
 {
-    return vser->vdev.features & (1 << VIRTIO_CONSOLE_F_MULTIPORT);
+    return vser->vdev.guest_features & (1 << VIRTIO_CONSOLE_F_MULTIPORT);
 }
 
 static size_t write_to_port(VirtIOSerialPort *port,
@@ -333,9 +333,11 @@ static void handle_input(VirtIODevice *v
 {
 }
 
-static uint32_t get_features(VirtIODevice *vdev)
+static uint32_t get_features(VirtIODevice *vdev, uint32_t features)
 {
-    return 1 << VIRTIO_CONSOLE_F_MULTIPORT;
+    features |= (1 << VIRTIO_CONSOLE_F_MULTIPORT);
+
+    return features;
 }
 
 /* Guest requested config info */


Index: qemu.spec
===================================================================
RCS file: /cvs/pkgs/rpms/qemu/devel/qemu.spec,v
retrieving revision 1.156
retrieving revision 1.157
diff -u -p -r1.156 -r1.157
--- qemu.spec	4 Feb 2010 15:58:29 -0000	1.156
+++ qemu.spec	9 Feb 2010 17:10:07 -0000	1.157
@@ -1,7 +1,7 @@
 Summary: QEMU is a FAST! processor emulator
 Name: qemu
 Version: 0.12.2
-Release: 5%{?dist}
+Release: 6%{?dist}
 # Epoch because we pushed a qemu-1.0 package
 Epoch: 2
 License: GPLv2+ and LGPLv2+ and BSD
@@ -37,6 +37,35 @@ Patch09: qemu-virtio-console-Rename-virt
 
 Patch10: qemu-v2-block-avoid-creating-too-large-iovecs-in-multiwrite_merge.patch
 
+# VHostNet Patches
+Patch11: qemu-net-add-API-to-disable-enable-polling.patch
+Patch12: qemu-virtio-rename-features-guest_features.patch
+Patch13: qemu-qdev-add-bit-property-type.patch
+Patch14: qemu-qdev-fix-thinko-leading-to-guest-crashes.patch
+Patch15: qemu-virtio-add-features-as-qdev-properties.patch
+Patch16: qemu-virtio-net-mac-property-is-mandatory.patch
+Patch17: qemu-exec-memory-notifiers.patch
+Patch18: qemu-kvm-add-API-to-set-ioeventfd.patch
+Patch19: qemu-notifier-event-notifier-implementation.patch
+Patch20: qemu-virtio-add-notifier-support.patch
+Patch21: qemu-virtio-add-APIs-for-queue-fields.patch
+Patch22: qemu-virtio-add-status-change-callback.patch
+Patch23: qemu-virtio-move-typedef-to-qemu-common.patch
+Patch24: qemu-virtio-pci-fill-in-notifier-support.patch
+Patch25: qemu-tap-add-interface-to-get-device-fd.patch
+Patch26: qemu-vhost-vhost-net-support.patch
+Patch27: qemu-tap-add-vhost-vhostfd-options.patch
+Patch28: qemu-tap-add-API-to-retrieve-vhost-net-header.patch
+Patch29: qemu-virtio-net-vhost-net-support.patch
+Patch30: qemu-kvm-add-vhost.h-header.patch
+Patch31: qemu-kvm-irqfd-support.patch
+Patch32: qemu-msix-add-mask-unmask-notifiers.patch
+Patch33: qemu-virtio-pci-irqfd-support.patch
+Patch34: qemu-virtio-avoid-crash-with-non-tap-backends.patch
+Patch35: qemu-virtio-serial-features-build-fix.patch
+Patch36: qemu-virtio-pci-irqfd-fix-nonkvm-build.patch
+Patch37: qemu-vhost-add-configure-check.patch
+
 
 BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
 BuildRequires: SDL-devel zlib-devel which texi2html gnutls-devel cyrus-sasl-devel
@@ -235,6 +264,33 @@ such as kvmtrace and kvm_stat.
 %patch08 -p1
 %patch09 -p1
 %patch10 -p1
+%patch11 -p1
+%patch12 -p1
+%patch13 -p1
+%patch14 -p1
+%patch15 -p1
+%patch16 -p1
+%patch17 -p1
+%patch18 -p1
+%patch19 -p1
+%patch20 -p1
+%patch21 -p1
+%patch22 -p1
+%patch23 -p1
+%patch24 -p1
+%patch25 -p1
+%patch26 -p1
+%patch27 -p1
+%patch28 -p1
+%patch29 -p1
+%patch30 -p1
+%patch31 -p1
+%patch32 -p1
+%patch33 -p1
+%patch34 -p1
+%patch35 -p1
+%patch36 -p1
+%patch37 -p1
 
 %build
 # --build-id option is used fedora 8 onwards for giving info to the debug packages.
@@ -518,6 +574,9 @@ fi
 %{_mandir}/man1/qemu-img.1*
 
 %changelog
+* Tue Feb 09 2010 Justin M. Forbes <jforbes at redhat.com> - 2:0.12.2-6
+- Add vhost net support.
+
 * Thu Feb 04 2010 Justin M. Forbes <jforbes at redhat.com> - 2:0.12.2-5
 - Avoid creating too large iovecs in multiwrite merge (#559717)
 - Don't try to set max_kernel_pages during ksm init on newer kernels (#558281)



More information about the scm-commits mailing list