diff options
| -rw-r--r-- | drivers/virtio/virtio_balloon.c | 20 | ||||
| -rw-r--r-- | tools/virtio/ringtest/Makefile | 5 | ||||
| -rw-r--r-- | tools/virtio/ringtest/main.c | 2 | ||||
| -rw-r--r-- | tools/virtio/ringtest/virtio_ring_0_9.c | 49 | ||||
| -rw-r--r-- | tools/virtio/ringtest/virtio_ring_inorder.c | 2 |
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 | ||
| 130 | static void set_page_pfns(u32 pfns[], struct page *page) | 130 | static 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 | ||
| 140 | static unsigned fill_balloon(struct virtio_balloon *vb, size_t num) | 142 | 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 | 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) | |||
| 177 | static void release_pages_balloon(struct virtio_balloon *vb) | 179 | static 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 @@ | |||
| 1 | all: | 1 | all: |
| 2 | 2 | ||
| 3 | all: ring virtio_ring_0_9 virtio_ring_poll | 3 | all: ring virtio_ring_0_9 virtio_ring_poll virtio_ring_inorder |
| 4 | 4 | ||
| 5 | CFLAGS += -Wall | 5 | CFLAGS += -Wall |
| 6 | CFLAGS += -pthread -O2 -ggdb | 6 | CFLAGS += -pthread -O2 -ggdb |
| @@ -10,13 +10,16 @@ main.o: main.c main.h | |||
| 10 | ring.o: ring.c main.h | 10 | ring.o: ring.c main.h |
| 11 | virtio_ring_0_9.o: virtio_ring_0_9.c main.h | 11 | virtio_ring_0_9.o: virtio_ring_0_9.c main.h |
| 12 | virtio_ring_poll.o: virtio_ring_poll.c virtio_ring_0_9.c main.h | 12 | virtio_ring_poll.o: virtio_ring_poll.c virtio_ring_0_9.c main.h |
| 13 | virtio_ring_inorder.o: virtio_ring_inorder.c virtio_ring_0_9.c main.h | ||
| 13 | ring: ring.o main.o | 14 | ring: ring.o main.o |
| 14 | virtio_ring_0_9: virtio_ring_0_9.o main.o | 15 | virtio_ring_0_9: virtio_ring_0_9.o main.o |
| 15 | virtio_ring_poll: virtio_ring_poll.o main.o | 16 | virtio_ring_poll: virtio_ring_poll.o main.o |
| 17 | virtio_ring_inorder: virtio_ring_inorder.o main.o | ||
| 16 | clean: | 18 | clean: |
| 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 */ |
| 85 | int add_inbuf(unsigned len, void *buf, void *datap) | 99 | int 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" | ||
