[PATCH] kvm tools: Support virtio indirect buffers

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

 



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>
---
 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)
-- 
1.7.8.rc3

--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]
  Powered by Linux