[tip:tools/kvm] kvm tools: Support virtio indirect buffers

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Commit-ID:  870a88b23331118c7999451a7f5601de517251f2
Gitweb:     http://git.kernel.org/tip/870a88b23331118c7999451a7f5601de517251f2
Author:     Sasha Levin <levinsasha928@xxxxxxxxx>
AuthorDate: Mon, 28 Nov 2011 19:54:27 +0200
Committer:  Pekka Enberg <penberg@xxxxxxxxxx>
CommitDate: Mon, 28 Nov 2011 22:50:55 +0200

kvm tools: Support virtio indirect buffers

Indirect buffers are ring descriptors which point to more (even more)
descriptors.

This can be used to increase the effective ring capacity, which helps the
guest to batch large requests - very useful for blk devices.

This patch also enables indirect buffers for virtio-net and virtio-blk.

The patch is based on the lguest's code which does the same.

Signed-off-by: Sasha Levin <levinsasha928@xxxxxxxxx>
Signed-off-by: Pekka Enberg <penberg@xxxxxxxxxx>
---
 tools/kvm/virtio/blk.c  |    3 ++-
 tools/kvm/virtio/core.c |   47 ++++++++++++++++++++++++++++++++++++++---------
 tools/kvm/virtio/net.c  |    3 ++-
 3 files changed, 42 insertions(+), 11 deletions(-)

diff --git a/tools/kvm/virtio/blk.c b/tools/kvm/virtio/blk.c
index 8c6f90b..d1a0197 100644
--- a/tools/kvm/virtio/blk.c
+++ b/tools/kvm/virtio/blk.c
@@ -148,7 +148,8 @@ static u32 get_host_features(struct kvm *kvm, void *dev)
 {
 	return	1UL << VIRTIO_BLK_F_SEG_MAX
 		| 1UL << VIRTIO_BLK_F_FLUSH
-		| 1UL << VIRTIO_RING_F_EVENT_IDX;
+		| 1UL << VIRTIO_RING_F_EVENT_IDX
+		| 1UL << VIRTIO_RING_F_INDIRECT_DESC;
 }
 
 static void set_guest_features(struct kvm *kvm, void *dev, u32 features)
diff --git a/tools/kvm/virtio/core.c b/tools/kvm/virtio/core.c
index a6f180e..fe9d588 100644
--- a/tools/kvm/virtio/core.c
+++ b/tools/kvm/virtio/core.c
@@ -33,27 +33,56 @@ struct vring_used_elem *virt_queue__set_used_elem(struct virt_queue *queue, u32
 	return used_elem;
 }
 
+/*
+ * Each buffer in the virtqueues is actually a chain of descriptors.  This
+ * function returns the next descriptor in the chain, or vq->vring.num if we're
+ * at the end.
+ */
+static unsigned next_desc(struct vring_desc *desc,
+			  unsigned int i, unsigned int max)
+{
+	unsigned int next;
+
+	/* If this descriptor says it doesn't chain, we're done. */
+	if (!(desc[i].flags & VRING_DESC_F_NEXT))
+		return max;
+
+	/* Check they're not leading us off end of descriptors. */
+	next = desc[i].next;
+	/* Make sure compiler knows to grab that: we don't want it changing! */
+	wmb();
+
+	return next;
+}
+
 u16 virt_queue__get_head_iov(struct virt_queue *vq, struct iovec iov[], u16 *out, u16 *in, u16 head, struct kvm *kvm)
 {
 	struct vring_desc *desc;
 	u16 idx;
+	u16 max;
 
 	idx = head;
 	*out = *in = 0;
+	max = vq->vring.num;
+	desc = vq->vring.desc;
+
+	if (desc[idx].flags & VRING_DESC_F_INDIRECT) {
+
+		max = desc[idx].len / sizeof(struct vring_desc);
+		desc = guest_flat_to_host(kvm, desc[idx].addr);
+		idx = 0;
+	}
 
 	do {
-		desc			 = virt_queue__get_desc(vq, idx);
-		iov[*out + *in].iov_base = guest_flat_to_host(kvm, desc->addr);
-		iov[*out + *in].iov_len	 = desc->len;
-		if (desc->flags & VRING_DESC_F_WRITE)
+		/* Grab the first descriptor, and check it's OK. */
+		iov[*out + *in].iov_len = desc[idx].len;
+		iov[*out + *in].iov_base = guest_flat_to_host(kvm, desc[idx].addr);
+		/* If this is an input descriptor, increment that count. */
+		if (desc[idx].flags & VRING_DESC_F_WRITE)
 			(*in)++;
 		else
 			(*out)++;
-		if (desc->flags & VRING_DESC_F_NEXT)
-			idx = desc->next;
-		else
-			break;
-	} while (1);
+	} while ((idx = next_desc(desc, idx, max)) != max);
 
 	return head;
 }
diff --git a/tools/kvm/virtio/net.c b/tools/kvm/virtio/net.c
index ce34555..3fb5054 100644
--- a/tools/kvm/virtio/net.c
+++ b/tools/kvm/virtio/net.c
@@ -318,7 +318,8 @@ static u32 get_host_features(struct kvm *kvm, void *dev)
 		| 1UL << VIRTIO_NET_F_GUEST_UFO
 		| 1UL << VIRTIO_NET_F_GUEST_TSO4
 		| 1UL << VIRTIO_NET_F_GUEST_TSO6
-		| 1UL << VIRTIO_RING_F_EVENT_IDX;
+		| 1UL << VIRTIO_RING_F_EVENT_IDX
+		| 1UL << VIRTIO_RING_F_INDIRECT_DESC;
 }
 
 static void set_guest_features(struct kvm *kvm, void *dev, u32 features)
--
To unsubscribe from this list: send the line "unsubscribe linux-tip-commits" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Stable Commits]     [Linux Stable Kernel]     [Linux Kernel]     [Linux USB Devel]     [Linux Video &Media]     [Linux Audio Users]     [Yosemite News]     [Linux SCSI]

  Powered by Linux