Commit ecaba718 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mst/vhost

Pull virtio updates from Michael Tsirkin:
 "Looks like a quiet cycle for virtio.  There's a new inorder option for
  the ringtest tool, and a bugfix for balloon for ppc platforms when
  using virtio 1 mode"

* tag 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mst/vhost:
  ringtest: pass buf != NULL
  virtio_balloon: fix PFN format for virtio-1
  virtio: add inorder option
parents e989cc56 bb991288
...@@ -75,7 +75,7 @@ struct virtio_balloon { ...@@ -75,7 +75,7 @@ struct virtio_balloon {
/* The array of pfns we tell the Host about. */ /* The array of pfns we tell the Host about. */
unsigned int num_pfns; unsigned int num_pfns;
u32 pfns[VIRTIO_BALLOON_ARRAY_PFNS_MAX]; __virtio32 pfns[VIRTIO_BALLOON_ARRAY_PFNS_MAX];
/* Memory statistics */ /* Memory statistics */
struct virtio_balloon_stat stats[VIRTIO_BALLOON_S_NR]; struct virtio_balloon_stat stats[VIRTIO_BALLOON_S_NR];
...@@ -127,14 +127,16 @@ static void tell_host(struct virtio_balloon *vb, struct virtqueue *vq) ...@@ -127,14 +127,16 @@ static void tell_host(struct virtio_balloon *vb, struct virtqueue *vq)
} }
static void set_page_pfns(u32 pfns[], struct page *page) static void set_page_pfns(struct virtio_balloon *vb,
__virtio32 pfns[], struct page *page)
{ {
unsigned int i; unsigned int i;
/* Set balloon pfns pointing at this page. /* Set balloon pfns pointing at this page.
* Note that the first pfn points at start of the page. */ * Note that the first pfn points at start of the page. */
for (i = 0; i < VIRTIO_BALLOON_PAGES_PER_PAGE; i++) for (i = 0; i < VIRTIO_BALLOON_PAGES_PER_PAGE; i++)
pfns[i] = page_to_balloon_pfn(page) + i; pfns[i] = cpu_to_virtio32(vb->vdev,
page_to_balloon_pfn(page) + i);
} }
static unsigned fill_balloon(struct virtio_balloon *vb, size_t num) static unsigned fill_balloon(struct virtio_balloon *vb, size_t num)
...@@ -158,7 +160,7 @@ static unsigned fill_balloon(struct virtio_balloon *vb, size_t num) ...@@ -158,7 +160,7 @@ static unsigned fill_balloon(struct virtio_balloon *vb, size_t num)
msleep(200); msleep(200);
break; break;
} }
set_page_pfns(vb->pfns + vb->num_pfns, page); set_page_pfns(vb, vb->pfns + vb->num_pfns, page);
vb->num_pages += VIRTIO_BALLOON_PAGES_PER_PAGE; vb->num_pages += VIRTIO_BALLOON_PAGES_PER_PAGE;
if (!virtio_has_feature(vb->vdev, if (!virtio_has_feature(vb->vdev,
VIRTIO_BALLOON_F_DEFLATE_ON_OOM)) VIRTIO_BALLOON_F_DEFLATE_ON_OOM))
...@@ -177,10 +179,12 @@ static unsigned fill_balloon(struct virtio_balloon *vb, size_t num) ...@@ -177,10 +179,12 @@ static unsigned fill_balloon(struct virtio_balloon *vb, size_t num)
static void release_pages_balloon(struct virtio_balloon *vb) static void release_pages_balloon(struct virtio_balloon *vb)
{ {
unsigned int i; unsigned int i;
struct page *page;
/* Find pfns pointing at start of each page, get pages and free them. */ /* Find pfns pointing at start of each page, get pages and free them. */
for (i = 0; i < vb->num_pfns; i += VIRTIO_BALLOON_PAGES_PER_PAGE) { for (i = 0; i < vb->num_pfns; i += VIRTIO_BALLOON_PAGES_PER_PAGE) {
struct page *page = balloon_pfn_to_page(vb->pfns[i]); page = balloon_pfn_to_page(virtio32_to_cpu(vb->vdev,
vb->pfns[i]));
if (!virtio_has_feature(vb->vdev, if (!virtio_has_feature(vb->vdev,
VIRTIO_BALLOON_F_DEFLATE_ON_OOM)) VIRTIO_BALLOON_F_DEFLATE_ON_OOM))
adjust_managed_page_count(page, 1); adjust_managed_page_count(page, 1);
...@@ -203,7 +207,7 @@ static unsigned leak_balloon(struct virtio_balloon *vb, size_t num) ...@@ -203,7 +207,7 @@ static unsigned leak_balloon(struct virtio_balloon *vb, size_t num)
page = balloon_page_dequeue(vb_dev_info); page = balloon_page_dequeue(vb_dev_info);
if (!page) if (!page)
break; break;
set_page_pfns(vb->pfns + vb->num_pfns, page); set_page_pfns(vb, vb->pfns + vb->num_pfns, page);
vb->num_pages -= VIRTIO_BALLOON_PAGES_PER_PAGE; vb->num_pages -= VIRTIO_BALLOON_PAGES_PER_PAGE;
} }
...@@ -471,13 +475,13 @@ static int virtballoon_migratepage(struct balloon_dev_info *vb_dev_info, ...@@ -471,13 +475,13 @@ static int virtballoon_migratepage(struct balloon_dev_info *vb_dev_info,
__count_vm_event(BALLOON_MIGRATE); __count_vm_event(BALLOON_MIGRATE);
spin_unlock_irqrestore(&vb_dev_info->pages_lock, flags); spin_unlock_irqrestore(&vb_dev_info->pages_lock, flags);
vb->num_pfns = VIRTIO_BALLOON_PAGES_PER_PAGE; vb->num_pfns = VIRTIO_BALLOON_PAGES_PER_PAGE;
set_page_pfns(vb->pfns, newpage); set_page_pfns(vb, vb->pfns, newpage);
tell_host(vb, vb->inflate_vq); tell_host(vb, vb->inflate_vq);
/* balloon's page migration 2nd step -- deflate "page" */ /* balloon's page migration 2nd step -- deflate "page" */
balloon_page_delete(page); balloon_page_delete(page);
vb->num_pfns = VIRTIO_BALLOON_PAGES_PER_PAGE; vb->num_pfns = VIRTIO_BALLOON_PAGES_PER_PAGE;
set_page_pfns(vb->pfns, page); set_page_pfns(vb, vb->pfns, page);
tell_host(vb, vb->deflate_vq); tell_host(vb, vb->deflate_vq);
mutex_unlock(&vb->balloon_lock); mutex_unlock(&vb->balloon_lock);
......
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 ...@@ -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
...@@ -115,7 +115,7 @@ static void run_guest(void) ...@@ -115,7 +115,7 @@ static void run_guest(void)
do { do {
if (started < bufs && if (started < bufs &&
started - completed < max_outstanding) { started - completed < max_outstanding) {
r = add_inbuf(0, NULL, "Hello, world!"); r = add_inbuf(0, "Buffer\n", "Hello, world!");
if (__builtin_expect(r == 0, true)) { if (__builtin_expect(r == 0, true)) {
++started; ++started;
if (!--tokick) { if (!--tokick) {
......
...@@ -26,6 +26,14 @@ struct vring ring; ...@@ -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 { ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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++;
......
#define INORDER 1
#include "virtio_ring_0_9.c"
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment