virtio: add inorder option
skips ring accesses but drops out of order support Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
This commit is contained in:
parent
2dcd0af568
commit
ce10c1b950
|
@ -1,6 +1,6 @@
|
||||||
all:
|
all:
|
||||||
|
|
||||||
all: ring virtio_ring_0_9 virtio_ring_poll
|
all: ring virtio_ring_0_9 virtio_ring_poll virtio_ring_inorder
|
||||||
|
|
||||||
CFLAGS += -Wall
|
CFLAGS += -Wall
|
||||||
CFLAGS += -pthread -O2 -ggdb
|
CFLAGS += -pthread -O2 -ggdb
|
||||||
|
@ -10,13 +10,16 @@ main.o: main.c main.h
|
||||||
ring.o: ring.c main.h
|
ring.o: ring.c main.h
|
||||||
virtio_ring_0_9.o: virtio_ring_0_9.c main.h
|
virtio_ring_0_9.o: virtio_ring_0_9.c main.h
|
||||||
virtio_ring_poll.o: virtio_ring_poll.c virtio_ring_0_9.c main.h
|
virtio_ring_poll.o: virtio_ring_poll.c virtio_ring_0_9.c main.h
|
||||||
|
virtio_ring_inorder.o: virtio_ring_inorder.c virtio_ring_0_9.c main.h
|
||||||
ring: ring.o main.o
|
ring: ring.o main.o
|
||||||
virtio_ring_0_9: virtio_ring_0_9.o main.o
|
virtio_ring_0_9: virtio_ring_0_9.o main.o
|
||||||
virtio_ring_poll: virtio_ring_poll.o main.o
|
virtio_ring_poll: virtio_ring_poll.o main.o
|
||||||
|
virtio_ring_inorder: virtio_ring_inorder.o main.o
|
||||||
clean:
|
clean:
|
||||||
-rm main.o
|
-rm main.o
|
||||||
-rm ring.o ring
|
-rm ring.o ring
|
||||||
-rm virtio_ring_0_9.o virtio_ring_0_9
|
-rm virtio_ring_0_9.o virtio_ring_0_9
|
||||||
-rm virtio_ring_poll.o virtio_ring_poll
|
-rm virtio_ring_poll.o virtio_ring_poll
|
||||||
|
-rm virtio_ring_inorder.o virtio_ring_inorder
|
||||||
|
|
||||||
.PHONY: all clean
|
.PHONY: all clean
|
||||||
|
|
|
@ -26,6 +26,14 @@ struct vring ring;
|
||||||
* high bits of ring id ^ 0x8000).
|
* high bits of ring id ^ 0x8000).
|
||||||
*/
|
*/
|
||||||
/* #ifdef RING_POLL */
|
/* #ifdef RING_POLL */
|
||||||
|
/* enabling the below activates experimental in-order code
|
||||||
|
* (which skips ring updates and reads and writes len in descriptor).
|
||||||
|
*/
|
||||||
|
/* #ifdef INORDER */
|
||||||
|
|
||||||
|
#if defined(RING_POLL) && defined(INORDER)
|
||||||
|
#error "RING_POLL and INORDER are mutually exclusive"
|
||||||
|
#endif
|
||||||
|
|
||||||
/* how much padding is needed to avoid false cache sharing */
|
/* how much padding is needed to avoid false cache sharing */
|
||||||
#define HOST_GUEST_PADDING 0x80
|
#define HOST_GUEST_PADDING 0x80
|
||||||
|
@ -35,7 +43,11 @@ struct guest {
|
||||||
unsigned short last_used_idx;
|
unsigned short last_used_idx;
|
||||||
unsigned short num_free;
|
unsigned short num_free;
|
||||||
unsigned short kicked_avail_idx;
|
unsigned short kicked_avail_idx;
|
||||||
|
#ifndef INORDER
|
||||||
unsigned short free_head;
|
unsigned short free_head;
|
||||||
|
#else
|
||||||
|
unsigned short reserved_free_head;
|
||||||
|
#endif
|
||||||
unsigned char reserved[HOST_GUEST_PADDING - 10];
|
unsigned char reserved[HOST_GUEST_PADDING - 10];
|
||||||
} guest;
|
} guest;
|
||||||
|
|
||||||
|
@ -66,8 +78,10 @@ void alloc_ring(void)
|
||||||
guest.avail_idx = 0;
|
guest.avail_idx = 0;
|
||||||
guest.kicked_avail_idx = -1;
|
guest.kicked_avail_idx = -1;
|
||||||
guest.last_used_idx = 0;
|
guest.last_used_idx = 0;
|
||||||
|
#ifndef INORDER
|
||||||
/* Put everything in free lists. */
|
/* Put everything in free lists. */
|
||||||
guest.free_head = 0;
|
guest.free_head = 0;
|
||||||
|
#endif
|
||||||
for (i = 0; i < ring_size - 1; i++)
|
for (i = 0; i < ring_size - 1; i++)
|
||||||
ring.desc[i].next = i + 1;
|
ring.desc[i].next = i + 1;
|
||||||
host.used_idx = 0;
|
host.used_idx = 0;
|
||||||
|
@ -84,13 +98,20 @@ void alloc_ring(void)
|
||||||
/* guest side */
|
/* guest side */
|
||||||
int add_inbuf(unsigned len, void *buf, void *datap)
|
int add_inbuf(unsigned len, void *buf, void *datap)
|
||||||
{
|
{
|
||||||
unsigned head, avail;
|
unsigned head;
|
||||||
|
#ifndef INORDER
|
||||||
|
unsigned avail;
|
||||||
|
#endif
|
||||||
struct vring_desc *desc;
|
struct vring_desc *desc;
|
||||||
|
|
||||||
if (!guest.num_free)
|
if (!guest.num_free)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
#ifdef INORDER
|
||||||
|
head = (ring_size - 1) & (guest.avail_idx++);
|
||||||
|
#else
|
||||||
head = guest.free_head;
|
head = guest.free_head;
|
||||||
|
#endif
|
||||||
guest.num_free--;
|
guest.num_free--;
|
||||||
|
|
||||||
desc = ring.desc;
|
desc = ring.desc;
|
||||||
|
@ -102,7 +123,9 @@ int add_inbuf(unsigned len, void *buf, void *datap)
|
||||||
* descriptors.
|
* descriptors.
|
||||||
*/
|
*/
|
||||||
desc[head].flags &= ~VRING_DESC_F_NEXT;
|
desc[head].flags &= ~VRING_DESC_F_NEXT;
|
||||||
|
#ifndef INORDER
|
||||||
guest.free_head = desc[head].next;
|
guest.free_head = desc[head].next;
|
||||||
|
#endif
|
||||||
|
|
||||||
data[head].data = datap;
|
data[head].data = datap;
|
||||||
|
|
||||||
|
@ -113,8 +136,12 @@ int add_inbuf(unsigned len, void *buf, void *datap)
|
||||||
ring.avail->ring[avail & (ring_size - 1)] =
|
ring.avail->ring[avail & (ring_size - 1)] =
|
||||||
(head | (avail & ~(ring_size - 1))) ^ 0x8000;
|
(head | (avail & ~(ring_size - 1))) ^ 0x8000;
|
||||||
#else
|
#else
|
||||||
|
#ifndef INORDER
|
||||||
|
/* Barrier A (for pairing) */
|
||||||
|
smp_release();
|
||||||
avail = (ring_size - 1) & (guest.avail_idx++);
|
avail = (ring_size - 1) & (guest.avail_idx++);
|
||||||
ring.avail->ring[avail] = head;
|
ring.avail->ring[avail] = head;
|
||||||
|
#endif
|
||||||
/* Barrier A (for pairing) */
|
/* Barrier A (for pairing) */
|
||||||
smp_release();
|
smp_release();
|
||||||
#endif
|
#endif
|
||||||
|
@ -141,15 +168,27 @@ void *get_buf(unsigned *lenp, void **bufp)
|
||||||
return NULL;
|
return NULL;
|
||||||
/* Barrier B (for pairing) */
|
/* Barrier B (for pairing) */
|
||||||
smp_acquire();
|
smp_acquire();
|
||||||
|
#ifdef INORDER
|
||||||
|
head = (ring_size - 1) & guest.last_used_idx;
|
||||||
|
index = head;
|
||||||
|
#else
|
||||||
head = (ring_size - 1) & guest.last_used_idx;
|
head = (ring_size - 1) & guest.last_used_idx;
|
||||||
index = ring.used->ring[head].id;
|
index = ring.used->ring[head].id;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
#ifdef INORDER
|
||||||
|
*lenp = ring.desc[index].len;
|
||||||
|
#else
|
||||||
*lenp = ring.used->ring[head].len;
|
*lenp = ring.used->ring[head].len;
|
||||||
|
#endif
|
||||||
datap = data[index].data;
|
datap = data[index].data;
|
||||||
*bufp = (void*)(unsigned long)ring.desc[index].addr;
|
*bufp = (void*)(unsigned long)ring.desc[index].addr;
|
||||||
data[index].data = NULL;
|
data[index].data = NULL;
|
||||||
|
#ifndef INORDER
|
||||||
ring.desc[index].next = guest.free_head;
|
ring.desc[index].next = guest.free_head;
|
||||||
guest.free_head = index;
|
guest.free_head = index;
|
||||||
|
#endif
|
||||||
guest.num_free++;
|
guest.num_free++;
|
||||||
guest.last_used_idx++;
|
guest.last_used_idx++;
|
||||||
return datap;
|
return datap;
|
||||||
|
@ -283,16 +322,24 @@ bool use_buf(unsigned *lenp, void **bufp)
|
||||||
smp_acquire();
|
smp_acquire();
|
||||||
|
|
||||||
used_idx &= ring_size - 1;
|
used_idx &= ring_size - 1;
|
||||||
|
#ifdef INORDER
|
||||||
|
head = used_idx;
|
||||||
|
#else
|
||||||
head = ring.avail->ring[used_idx];
|
head = ring.avail->ring[used_idx];
|
||||||
|
#endif
|
||||||
desc = &ring.desc[head];
|
desc = &ring.desc[head];
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
*lenp = desc->len;
|
*lenp = desc->len;
|
||||||
*bufp = (void *)(unsigned long)desc->addr;
|
*bufp = (void *)(unsigned long)desc->addr;
|
||||||
|
|
||||||
|
#ifdef INORDER
|
||||||
|
desc->len = desc->len - 1;
|
||||||
|
#else
|
||||||
/* now update used ring */
|
/* now update used ring */
|
||||||
ring.used->ring[used_idx].id = head;
|
ring.used->ring[used_idx].id = head;
|
||||||
ring.used->ring[used_idx].len = desc->len - 1;
|
ring.used->ring[used_idx].len = desc->len - 1;
|
||||||
|
#endif
|
||||||
/* Barrier B (for pairing) */
|
/* Barrier B (for pairing) */
|
||||||
smp_release();
|
smp_release();
|
||||||
host.used_idx++;
|
host.used_idx++;
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
#define INORDER 1
|
||||||
|
#include "virtio_ring_0_9.c"
|
Loading…
Reference in New Issue