virtio: patches for 4.7
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. Signed-off-by: Michael S. Tsirkin <mst@redhat.com> -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQEcBAABAgAGBQJXREFSAAoJECgfDbjSjVRp2jUH/AwiS+KEpJGusr8TodRxYbnc 7TKPsGwHGKd/zRdG+FEzIWgt4aAg3yGH0+ERa+++H/7VYLiVDTLso5GXYHd07iG6 dTzj0vioBorhsNczjixHqdlgPNBA/1eNQMTPCRgTFcYeRzRiV+lhgdFD7aqaOMkX Z6fuhwyUx1YBkN8Vvi5CrxlHEA3EUv0CUSNtz3Rv5rZppYF/JA58K2NsPWGPCzm5 k9IBdbxmcQ5DNsdjpkwEoNPYwFT9Powjh3QFy4b5Nh+ZR44ioowZ7Zdke3UC2hHA LSVtn4FNfJ61aAyB08dSzOpUCUnL7eo+WjDY7kDd2Od1iyi+fjKOCnXXV2JkQew= =wuJb -----END PGP SIGNATURE----- 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
This commit is contained in:
commit
ecaba71858
|
@ -75,7 +75,7 @@ struct virtio_balloon {
|
|||
|
||||
/* The array of pfns we tell the Host about. */
|
||||
unsigned int num_pfns;
|
||||
u32 pfns[VIRTIO_BALLOON_ARRAY_PFNS_MAX];
|
||||
__virtio32 pfns[VIRTIO_BALLOON_ARRAY_PFNS_MAX];
|
||||
|
||||
/* Memory statistics */
|
||||
struct virtio_balloon_stat stats[VIRTIO_BALLOON_S_NR];
|
||||
|
@ -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;
|
||||
|
||||
/* Set balloon pfns pointing at this page.
|
||||
* Note that the first pfn points at start of the page. */
|
||||
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)
|
||||
|
@ -158,7 +160,7 @@ static unsigned fill_balloon(struct virtio_balloon *vb, size_t num)
|
|||
msleep(200);
|
||||
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;
|
||||
if (!virtio_has_feature(vb->vdev,
|
||||
VIRTIO_BALLOON_F_DEFLATE_ON_OOM))
|
||||
|
@ -177,10 +179,12 @@ static unsigned fill_balloon(struct virtio_balloon *vb, size_t num)
|
|||
static void release_pages_balloon(struct virtio_balloon *vb)
|
||||
{
|
||||
unsigned int i;
|
||||
struct page *page;
|
||||
|
||||
/* 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) {
|
||||
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,
|
||||
VIRTIO_BALLOON_F_DEFLATE_ON_OOM))
|
||||
adjust_managed_page_count(page, 1);
|
||||
|
@ -203,7 +207,7 @@ static unsigned leak_balloon(struct virtio_balloon *vb, size_t num)
|
|||
page = balloon_page_dequeue(vb_dev_info);
|
||||
if (!page)
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -471,13 +475,13 @@ static int virtballoon_migratepage(struct balloon_dev_info *vb_dev_info,
|
|||
__count_vm_event(BALLOON_MIGRATE);
|
||||
spin_unlock_irqrestore(&vb_dev_info->pages_lock, flags);
|
||||
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);
|
||||
|
||||
/* balloon's page migration 2nd step -- deflate "page" */
|
||||
balloon_page_delete(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);
|
||||
|
||||
mutex_unlock(&vb->balloon_lock);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
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 += -pthread -O2 -ggdb
|
||||
|
@ -10,13 +10,16 @@ main.o: main.c main.h
|
|||
ring.o: ring.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_inorder.o: virtio_ring_inorder.c virtio_ring_0_9.c main.h
|
||||
ring: ring.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_inorder: virtio_ring_inorder.o main.o
|
||||
clean:
|
||||
-rm main.o
|
||||
-rm ring.o ring
|
||||
-rm virtio_ring_0_9.o virtio_ring_0_9
|
||||
-rm virtio_ring_poll.o virtio_ring_poll
|
||||
-rm virtio_ring_inorder.o virtio_ring_inorder
|
||||
|
||||
.PHONY: all clean
|
||||
|
|
|
@ -115,7 +115,7 @@ static void run_guest(void)
|
|||
do {
|
||||
if (started < bufs &&
|
||||
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)) {
|
||||
++started;
|
||||
if (!--tokick) {
|
||||
|
|
|
@ -26,6 +26,14 @@ struct vring ring;
|
|||
* high bits of ring id ^ 0x8000).
|
||||
*/
|
||||
/* #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 */
|
||||
#define HOST_GUEST_PADDING 0x80
|
||||
|
@ -35,7 +43,11 @@ struct guest {
|
|||
unsigned short last_used_idx;
|
||||
unsigned short num_free;
|
||||
unsigned short kicked_avail_idx;
|
||||
#ifndef INORDER
|
||||
unsigned short free_head;
|
||||
#else
|
||||
unsigned short reserved_free_head;
|
||||
#endif
|
||||
unsigned char reserved[HOST_GUEST_PADDING - 10];
|
||||
} guest;
|
||||
|
||||
|
@ -66,8 +78,10 @@ void alloc_ring(void)
|
|||
guest.avail_idx = 0;
|
||||
guest.kicked_avail_idx = -1;
|
||||
guest.last_used_idx = 0;
|
||||
#ifndef INORDER
|
||||
/* Put everything in free lists. */
|
||||
guest.free_head = 0;
|
||||
#endif
|
||||
for (i = 0; i < ring_size - 1; i++)
|
||||
ring.desc[i].next = i + 1;
|
||||
host.used_idx = 0;
|
||||
|
@ -84,13 +98,20 @@ void alloc_ring(void)
|
|||
/* guest side */
|
||||
int add_inbuf(unsigned len, void *buf, void *datap)
|
||||
{
|
||||
unsigned head, avail;
|
||||
unsigned head;
|
||||
#ifndef INORDER
|
||||
unsigned avail;
|
||||
#endif
|
||||
struct vring_desc *desc;
|
||||
|
||||
if (!guest.num_free)
|
||||
return -1;
|
||||
|
||||
#ifdef INORDER
|
||||
head = (ring_size - 1) & (guest.avail_idx++);
|
||||
#else
|
||||
head = guest.free_head;
|
||||
#endif
|
||||
guest.num_free--;
|
||||
|
||||
desc = ring.desc;
|
||||
|
@ -102,7 +123,9 @@ int add_inbuf(unsigned len, void *buf, void *datap)
|
|||
* descriptors.
|
||||
*/
|
||||
desc[head].flags &= ~VRING_DESC_F_NEXT;
|
||||
#ifndef INORDER
|
||||
guest.free_head = desc[head].next;
|
||||
#endif
|
||||
|
||||
data[head].data = datap;
|
||||
|
||||
|
@ -113,8 +136,12 @@ int add_inbuf(unsigned len, void *buf, void *datap)
|
|||
ring.avail->ring[avail & (ring_size - 1)] =
|
||||
(head | (avail & ~(ring_size - 1))) ^ 0x8000;
|
||||
#else
|
||||
#ifndef INORDER
|
||||
/* Barrier A (for pairing) */
|
||||
smp_release();
|
||||
avail = (ring_size - 1) & (guest.avail_idx++);
|
||||
ring.avail->ring[avail] = head;
|
||||
#endif
|
||||
/* Barrier A (for pairing) */
|
||||
smp_release();
|
||||
#endif
|
||||
|
@ -141,15 +168,27 @@ void *get_buf(unsigned *lenp, void **bufp)
|
|||
return NULL;
|
||||
/* Barrier B (for pairing) */
|
||||
smp_acquire();
|
||||
#ifdef INORDER
|
||||
head = (ring_size - 1) & guest.last_used_idx;
|
||||
index = head;
|
||||
#else
|
||||
head = (ring_size - 1) & guest.last_used_idx;
|
||||
index = ring.used->ring[head].id;
|
||||
#endif
|
||||
|
||||
#endif
|
||||
#ifdef INORDER
|
||||
*lenp = ring.desc[index].len;
|
||||
#else
|
||||
*lenp = ring.used->ring[head].len;
|
||||
#endif
|
||||
datap = data[index].data;
|
||||
*bufp = (void*)(unsigned long)ring.desc[index].addr;
|
||||
data[index].data = NULL;
|
||||
#ifndef INORDER
|
||||
ring.desc[index].next = guest.free_head;
|
||||
guest.free_head = index;
|
||||
#endif
|
||||
guest.num_free++;
|
||||
guest.last_used_idx++;
|
||||
return datap;
|
||||
|
@ -283,16 +322,24 @@ bool use_buf(unsigned *lenp, void **bufp)
|
|||
smp_acquire();
|
||||
|
||||
used_idx &= ring_size - 1;
|
||||
#ifdef INORDER
|
||||
head = used_idx;
|
||||
#else
|
||||
head = ring.avail->ring[used_idx];
|
||||
#endif
|
||||
desc = &ring.desc[head];
|
||||
#endif
|
||||
|
||||
*lenp = desc->len;
|
||||
*bufp = (void *)(unsigned long)desc->addr;
|
||||
|
||||
#ifdef INORDER
|
||||
desc->len = desc->len - 1;
|
||||
#else
|
||||
/* now update used ring */
|
||||
ring.used->ring[used_idx].id = head;
|
||||
ring.used->ring[used_idx].len = desc->len - 1;
|
||||
#endif
|
||||
/* Barrier B (for pairing) */
|
||||
smp_release();
|
||||
host.used_idx++;
|
||||
|
|
2
tools/virtio/ringtest/virtio_ring_inorder.c
Normal file
2
tools/virtio/ringtest/virtio_ring_inorder.c
Normal file
|
@ -0,0 +1,2 @@
|
|||
#define INORDER 1
|
||||
#include "virtio_ring_0_9.c"
|
Loading…
Reference in a new issue