aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/virtio/virtio_balloon.c20
-rw-r--r--tools/virtio/ringtest/Makefile5
-rw-r--r--tools/virtio/ringtest/main.c2
-rw-r--r--tools/virtio/ringtest/virtio_ring_0_9.c49
-rw-r--r--tools/virtio/ringtest/virtio_ring_inorder.c2
5 files changed, 67 insertions, 11 deletions
diff --git a/drivers/virtio/virtio_balloon.c b/drivers/virtio/virtio_balloon.c
index 7b6d74f0c72f..476c0e3a7150 100644
--- a/drivers/virtio/virtio_balloon.c
+++ b/drivers/virtio/virtio_balloon.c
@@ -75,7 +75,7 @@ struct virtio_balloon {
75 75
76 /* The array of pfns we tell the Host about. */ 76 /* The array of pfns we tell the Host about. */
77 unsigned int num_pfns; 77 unsigned int num_pfns;
78 u32 pfns[VIRTIO_BALLOON_ARRAY_PFNS_MAX]; 78 __virtio32 pfns[VIRTIO_BALLOON_ARRAY_PFNS_MAX];
79 79
80 /* Memory statistics */ 80 /* Memory statistics */
81 struct virtio_balloon_stat stats[VIRTIO_BALLOON_S_NR]; 81 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 127
128} 128}
129 129
130static void set_page_pfns(u32 pfns[], struct page *page) 130static void set_page_pfns(struct virtio_balloon *vb,
131 __virtio32 pfns[], struct page *page)
131{ 132{
132 unsigned int i; 133 unsigned int i;
133 134
134 /* Set balloon pfns pointing at this page. 135 /* Set balloon pfns pointing at this page.
135 * Note that the first pfn points at start of the page. */ 136 * Note that the first pfn points at start of the page. */
136 for (i = 0; i < VIRTIO_BALLOON_PAGES_PER_PAGE; i++) 137 for (i = 0; i < VIRTIO_BALLOON_PAGES_PER_PAGE; i++)
137 pfns[i] = page_to_balloon_pfn(page) + i; 138 pfns[i] = cpu_to_virtio32(vb->vdev,
139 page_to_balloon_pfn(page) + i);
138} 140}
139 141
140static unsigned fill_balloon(struct virtio_balloon *vb, size_t num) 142static 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 msleep(200); 160 msleep(200);
159 break; 161 break;
160 } 162 }
161 set_page_pfns(vb->pfns + vb->num_pfns, page); 163 set_page_pfns(vb, vb->pfns + vb->num_pfns, page);
162 vb->num_pages += VIRTIO_BALLOON_PAGES_PER_PAGE; 164 vb->num_pages += VIRTIO_BALLOON_PAGES_PER_PAGE;
163 if (!virtio_has_feature(vb->vdev, 165 if (!virtio_has_feature(vb->vdev,
164 VIRTIO_BALLOON_F_DEFLATE_ON_OOM)) 166 VIRTIO_BALLOON_F_DEFLATE_ON_OOM))
@@ -177,10 +179,12 @@ static unsigned fill_balloon(struct virtio_balloon *vb, size_t num)
177static void release_pages_balloon(struct virtio_balloon *vb) 179static void release_pages_balloon(struct virtio_balloon *vb)
178{ 180{
179 unsigned int i; 181 unsigned int i;
182 struct page *page;
180 183
181 /* Find pfns pointing at start of each page, get pages and free them. */ 184 /* Find pfns pointing at start of each page, get pages and free them. */
182 for (i = 0; i < vb->num_pfns; i += VIRTIO_BALLOON_PAGES_PER_PAGE) { 185 for (i = 0; i < vb->num_pfns; i += VIRTIO_BALLOON_PAGES_PER_PAGE) {
183 struct page *page = balloon_pfn_to_page(vb->pfns[i]); 186 page = balloon_pfn_to_page(virtio32_to_cpu(vb->vdev,
187 vb->pfns[i]));
184 if (!virtio_has_feature(vb->vdev, 188 if (!virtio_has_feature(vb->vdev,
185 VIRTIO_BALLOON_F_DEFLATE_ON_OOM)) 189 VIRTIO_BALLOON_F_DEFLATE_ON_OOM))
186 adjust_managed_page_count(page, 1); 190 adjust_managed_page_count(page, 1);
@@ -203,7 +207,7 @@ static unsigned leak_balloon(struct virtio_balloon *vb, size_t num)
203 page = balloon_page_dequeue(vb_dev_info); 207 page = balloon_page_dequeue(vb_dev_info);
204 if (!page) 208 if (!page)
205 break; 209 break;
206 set_page_pfns(vb->pfns + vb->num_pfns, page); 210 set_page_pfns(vb, vb->pfns + vb->num_pfns, page);
207 vb->num_pages -= VIRTIO_BALLOON_PAGES_PER_PAGE; 211 vb->num_pages -= VIRTIO_BALLOON_PAGES_PER_PAGE;
208 } 212 }
209 213
@@ -471,13 +475,13 @@ static int virtballoon_migratepage(struct balloon_dev_info *vb_dev_info,
471 __count_vm_event(BALLOON_MIGRATE); 475 __count_vm_event(BALLOON_MIGRATE);
472 spin_unlock_irqrestore(&vb_dev_info->pages_lock, flags); 476 spin_unlock_irqrestore(&vb_dev_info->pages_lock, flags);
473 vb->num_pfns = VIRTIO_BALLOON_PAGES_PER_PAGE; 477 vb->num_pfns = VIRTIO_BALLOON_PAGES_PER_PAGE;
474 set_page_pfns(vb->pfns, newpage); 478 set_page_pfns(vb, vb->pfns, newpage);
475 tell_host(vb, vb->inflate_vq); 479 tell_host(vb, vb->inflate_vq);
476 480
477 /* balloon's page migration 2nd step -- deflate "page" */ 481 /* balloon's page migration 2nd step -- deflate "page" */
478 balloon_page_delete(page); 482 balloon_page_delete(page);
479 vb->num_pfns = VIRTIO_BALLOON_PAGES_PER_PAGE; 483 vb->num_pfns = VIRTIO_BALLOON_PAGES_PER_PAGE;
480 set_page_pfns(vb->pfns, page); 484 set_page_pfns(vb, vb->pfns, page);
481 tell_host(vb, vb->deflate_vq); 485 tell_host(vb, vb->deflate_vq);
482 486
483 mutex_unlock(&vb->balloon_lock); 487 mutex_unlock(&vb->balloon_lock);
diff --git a/tools/virtio/ringtest/Makefile b/tools/virtio/ringtest/Makefile
index feaa64ac4630..6ba745529833 100644
--- a/tools/virtio/ringtest/Makefile
+++ b/tools/virtio/ringtest/Makefile
@@ -1,6 +1,6 @@
1all: 1all:
2 2
3all: ring virtio_ring_0_9 virtio_ring_poll 3all: ring virtio_ring_0_9 virtio_ring_poll virtio_ring_inorder
4 4
5CFLAGS += -Wall 5CFLAGS += -Wall
6CFLAGS += -pthread -O2 -ggdb 6CFLAGS += -pthread -O2 -ggdb
@@ -10,13 +10,16 @@ main.o: main.c main.h
10ring.o: ring.c main.h 10ring.o: ring.c main.h
11virtio_ring_0_9.o: virtio_ring_0_9.c main.h 11virtio_ring_0_9.o: virtio_ring_0_9.c main.h
12virtio_ring_poll.o: virtio_ring_poll.c virtio_ring_0_9.c main.h 12virtio_ring_poll.o: virtio_ring_poll.c virtio_ring_0_9.c main.h
13virtio_ring_inorder.o: virtio_ring_inorder.c virtio_ring_0_9.c main.h
13ring: ring.o main.o 14ring: ring.o main.o
14virtio_ring_0_9: virtio_ring_0_9.o main.o 15virtio_ring_0_9: virtio_ring_0_9.o main.o
15virtio_ring_poll: virtio_ring_poll.o main.o 16virtio_ring_poll: virtio_ring_poll.o main.o
17virtio_ring_inorder: virtio_ring_inorder.o main.o
16clean: 18clean:
17 -rm main.o 19 -rm main.o
18 -rm ring.o ring 20 -rm ring.o ring
19 -rm virtio_ring_0_9.o virtio_ring_0_9 21 -rm virtio_ring_0_9.o virtio_ring_0_9
20 -rm virtio_ring_poll.o virtio_ring_poll 22 -rm virtio_ring_poll.o virtio_ring_poll
23 -rm virtio_ring_inorder.o virtio_ring_inorder
21 24
22.PHONY: all clean 25.PHONY: all clean
diff --git a/tools/virtio/ringtest/main.c b/tools/virtio/ringtest/main.c
index 3a5ff438bd62..147abb452a6c 100644
--- a/tools/virtio/ringtest/main.c
+++ b/tools/virtio/ringtest/main.c
@@ -115,7 +115,7 @@ static void run_guest(void)
115 do { 115 do {
116 if (started < bufs && 116 if (started < bufs &&
117 started - completed < max_outstanding) { 117 started - completed < max_outstanding) {
118 r = add_inbuf(0, NULL, "Hello, world!"); 118 r = add_inbuf(0, "Buffer\n", "Hello, world!");
119 if (__builtin_expect(r == 0, true)) { 119 if (__builtin_expect(r == 0, true)) {
120 ++started; 120 ++started;
121 if (!--tokick) { 121 if (!--tokick) {
diff --git a/tools/virtio/ringtest/virtio_ring_0_9.c b/tools/virtio/ringtest/virtio_ring_0_9.c
index 47c9a1a18d36..761866212aac 100644
--- a/tools/virtio/ringtest/virtio_ring_0_9.c
+++ b/tools/virtio/ringtest/virtio_ring_0_9.c
@@ -26,6 +26,14 @@ struct vring ring;
26 * high bits of ring id ^ 0x8000). 26 * high bits of ring id ^ 0x8000).
27 */ 27 */
28/* #ifdef RING_POLL */ 28/* #ifdef RING_POLL */
29/* enabling the below activates experimental in-order code
30 * (which skips ring updates and reads and writes len in descriptor).
31 */
32/* #ifdef INORDER */
33
34#if defined(RING_POLL) && defined(INORDER)
35#error "RING_POLL and INORDER are mutually exclusive"
36#endif
29 37
30/* how much padding is needed to avoid false cache sharing */ 38/* how much padding is needed to avoid false cache sharing */
31#define HOST_GUEST_PADDING 0x80 39#define HOST_GUEST_PADDING 0x80
@@ -35,7 +43,11 @@ struct guest {
35 unsigned short last_used_idx; 43 unsigned short last_used_idx;
36 unsigned short num_free; 44 unsigned short num_free;
37 unsigned short kicked_avail_idx; 45 unsigned short kicked_avail_idx;
46#ifndef INORDER
38 unsigned short free_head; 47 unsigned short free_head;
48#else
49 unsigned short reserved_free_head;
50#endif
39 unsigned char reserved[HOST_GUEST_PADDING - 10]; 51 unsigned char reserved[HOST_GUEST_PADDING - 10];
40} guest; 52} guest;
41 53
@@ -66,8 +78,10 @@ void alloc_ring(void)
66 guest.avail_idx = 0; 78 guest.avail_idx = 0;
67 guest.kicked_avail_idx = -1; 79 guest.kicked_avail_idx = -1;
68 guest.last_used_idx = 0; 80 guest.last_used_idx = 0;
81#ifndef INORDER
69 /* Put everything in free lists. */ 82 /* Put everything in free lists. */
70 guest.free_head = 0; 83 guest.free_head = 0;
84#endif
71 for (i = 0; i < ring_size - 1; i++) 85 for (i = 0; i < ring_size - 1; i++)
72 ring.desc[i].next = i + 1; 86 ring.desc[i].next = i + 1;
73 host.used_idx = 0; 87 host.used_idx = 0;
@@ -84,13 +98,20 @@ void alloc_ring(void)
84/* guest side */ 98/* guest side */
85int add_inbuf(unsigned len, void *buf, void *datap) 99int add_inbuf(unsigned len, void *buf, void *datap)
86{ 100{
87 unsigned head, avail; 101 unsigned head;
102#ifndef INORDER
103 unsigned avail;
104#endif
88 struct vring_desc *desc; 105 struct vring_desc *desc;
89 106
90 if (!guest.num_free) 107 if (!guest.num_free)
91 return -1; 108 return -1;
92 109
110#ifdef INORDER
111 head = (ring_size - 1) & (guest.avail_idx++);
112#else
93 head = guest.free_head; 113 head = guest.free_head;
114#endif
94 guest.num_free--; 115 guest.num_free--;
95 116
96 desc = ring.desc; 117 desc = ring.desc;
@@ -102,7 +123,9 @@ int add_inbuf(unsigned len, void *buf, void *datap)
102 * descriptors. 123 * descriptors.
103 */ 124 */
104 desc[head].flags &= ~VRING_DESC_F_NEXT; 125 desc[head].flags &= ~VRING_DESC_F_NEXT;
126#ifndef INORDER
105 guest.free_head = desc[head].next; 127 guest.free_head = desc[head].next;
128#endif
106 129
107 data[head].data = datap; 130 data[head].data = datap;
108 131
@@ -113,8 +136,12 @@ int add_inbuf(unsigned len, void *buf, void *datap)
113 ring.avail->ring[avail & (ring_size - 1)] = 136 ring.avail->ring[avail & (ring_size - 1)] =
114 (head | (avail & ~(ring_size - 1))) ^ 0x8000; 137 (head | (avail & ~(ring_size - 1))) ^ 0x8000;
115#else 138#else
139#ifndef INORDER
140 /* Barrier A (for pairing) */
141 smp_release();
116 avail = (ring_size - 1) & (guest.avail_idx++); 142 avail = (ring_size - 1) & (guest.avail_idx++);
117 ring.avail->ring[avail] = head; 143 ring.avail->ring[avail] = head;
144#endif
118 /* Barrier A (for pairing) */ 145 /* Barrier A (for pairing) */
119 smp_release(); 146 smp_release();
120#endif 147#endif
@@ -141,15 +168,27 @@ void *get_buf(unsigned *lenp, void **bufp)
141 return NULL; 168 return NULL;
142 /* Barrier B (for pairing) */ 169 /* Barrier B (for pairing) */
143 smp_acquire(); 170 smp_acquire();
171#ifdef INORDER
172 head = (ring_size - 1) & guest.last_used_idx;
173 index = head;
174#else
144 head = (ring_size - 1) & guest.last_used_idx; 175 head = (ring_size - 1) & guest.last_used_idx;
145 index = ring.used->ring[head].id; 176 index = ring.used->ring[head].id;
146#endif 177#endif
178
179#endif
180#ifdef INORDER
181 *lenp = ring.desc[index].len;
182#else
147 *lenp = ring.used->ring[head].len; 183 *lenp = ring.used->ring[head].len;
184#endif
148 datap = data[index].data; 185 datap = data[index].data;
149 *bufp = (void*)(unsigned long)ring.desc[index].addr; 186 *bufp = (void*)(unsigned long)ring.desc[index].addr;
150 data[index].data = NULL; 187 data[index].data = NULL;
188#ifndef INORDER
151 ring.desc[index].next = guest.free_head; 189 ring.desc[index].next = guest.free_head;
152 guest.free_head = index; 190 guest.free_head = index;
191#endif
153 guest.num_free++; 192 guest.num_free++;
154 guest.last_used_idx++; 193 guest.last_used_idx++;
155 return datap; 194 return datap;
@@ -283,16 +322,24 @@ bool use_buf(unsigned *lenp, void **bufp)
283 smp_acquire(); 322 smp_acquire();
284 323
285 used_idx &= ring_size - 1; 324 used_idx &= ring_size - 1;
325#ifdef INORDER
326 head = used_idx;
327#else
286 head = ring.avail->ring[used_idx]; 328 head = ring.avail->ring[used_idx];
329#endif
287 desc = &ring.desc[head]; 330 desc = &ring.desc[head];
288#endif 331#endif
289 332
290 *lenp = desc->len; 333 *lenp = desc->len;
291 *bufp = (void *)(unsigned long)desc->addr; 334 *bufp = (void *)(unsigned long)desc->addr;
292 335
336#ifdef INORDER
337 desc->len = desc->len - 1;
338#else
293 /* now update used ring */ 339 /* now update used ring */
294 ring.used->ring[used_idx].id = head; 340 ring.used->ring[used_idx].id = head;
295 ring.used->ring[used_idx].len = desc->len - 1; 341 ring.used->ring[used_idx].len = desc->len - 1;
342#endif
296 /* Barrier B (for pairing) */ 343 /* Barrier B (for pairing) */
297 smp_release(); 344 smp_release();
298 host.used_idx++; 345 host.used_idx++;
diff --git a/tools/virtio/ringtest/virtio_ring_inorder.c b/tools/virtio/ringtest/virtio_ring_inorder.c
new file mode 100644
index 000000000000..2438ca58a2ad
--- /dev/null
+++ b/tools/virtio/ringtest/virtio_ring_inorder.c
@@ -0,0 +1,2 @@
1#define INORDER 1
2#include "virtio_ring_0_9.c"