virtio_ring_0_9.c 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316
  1. /*
  2. * Copyright (C) 2016 Red Hat, Inc.
  3. * Author: Michael S. Tsirkin <mst@redhat.com>
  4. * This work is licensed under the terms of the GNU GPL, version 2.
  5. *
  6. * Partial implementation of virtio 0.9. event index is used for signalling,
  7. * unconditionally. Design roughly follows linux kernel implementation in order
  8. * to be able to judge its performance.
  9. */
  10. #define _GNU_SOURCE
  11. #include "main.h"
  12. #include <stdlib.h>
  13. #include <stdio.h>
  14. #include <assert.h>
  15. #include <string.h>
  16. #include <linux/virtio_ring.h>
  17. struct data {
  18. void *data;
  19. } *data;
  20. struct vring ring;
  21. /* enabling the below activates experimental ring polling code
  22. * (which skips index reads on consumer in favor of looking at
  23. * high bits of ring id ^ 0x8000).
  24. */
  25. /* #ifdef RING_POLL */
  26. /* how much padding is needed to avoid false cache sharing */
  27. #define HOST_GUEST_PADDING 0x80
  28. struct guest {
  29. unsigned short avail_idx;
  30. unsigned short last_used_idx;
  31. unsigned short num_free;
  32. unsigned short kicked_avail_idx;
  33. unsigned short free_head;
  34. unsigned char reserved[HOST_GUEST_PADDING - 10];
  35. } guest;
  36. struct host {
  37. /* we do not need to track last avail index
  38. * unless we have more than one in flight.
  39. */
  40. unsigned short used_idx;
  41. unsigned short called_used_idx;
  42. unsigned char reserved[HOST_GUEST_PADDING - 4];
  43. } host;
  44. /* implemented by ring */
  45. void alloc_ring(void)
  46. {
  47. int ret;
  48. int i;
  49. void *p;
  50. ret = posix_memalign(&p, 0x1000, vring_size(ring_size, 0x1000));
  51. if (ret) {
  52. perror("Unable to allocate ring buffer.\n");
  53. exit(3);
  54. }
  55. memset(p, 0, vring_size(ring_size, 0x1000));
  56. vring_init(&ring, ring_size, p, 0x1000);
  57. guest.avail_idx = 0;
  58. guest.kicked_avail_idx = -1;
  59. guest.last_used_idx = 0;
  60. /* Put everything in free lists. */
  61. guest.free_head = 0;
  62. for (i = 0; i < ring_size - 1; i++)
  63. ring.desc[i].next = i + 1;
  64. host.used_idx = 0;
  65. host.called_used_idx = -1;
  66. guest.num_free = ring_size;
  67. data = malloc(ring_size * sizeof *data);
  68. if (!data) {
  69. perror("Unable to allocate data buffer.\n");
  70. exit(3);
  71. }
  72. memset(data, 0, ring_size * sizeof *data);
  73. }
  74. /* guest side */
  75. int add_inbuf(unsigned len, void *buf, void *datap)
  76. {
  77. unsigned head, avail;
  78. struct vring_desc *desc;
  79. if (!guest.num_free)
  80. return -1;
  81. head = guest.free_head;
  82. guest.num_free--;
  83. desc = ring.desc;
  84. desc[head].flags = VRING_DESC_F_NEXT;
  85. desc[head].addr = (unsigned long)(void *)buf;
  86. desc[head].len = len;
  87. /* We do it like this to simulate the way
  88. * we'd have to flip it if we had multiple
  89. * descriptors.
  90. */
  91. desc[head].flags &= ~VRING_DESC_F_NEXT;
  92. guest.free_head = desc[head].next;
  93. data[head].data = datap;
  94. #ifdef RING_POLL
  95. /* Barrier A (for pairing) */
  96. smp_release();
  97. avail = guest.avail_idx++;
  98. ring.avail->ring[avail & (ring_size - 1)] =
  99. (head | (avail & ~(ring_size - 1))) ^ 0x8000;
  100. #else
  101. avail = (ring_size - 1) & (guest.avail_idx++);
  102. ring.avail->ring[avail] = head;
  103. /* Barrier A (for pairing) */
  104. smp_release();
  105. #endif
  106. ring.avail->idx = guest.avail_idx;
  107. return 0;
  108. }
  109. void *get_buf(unsigned *lenp, void **bufp)
  110. {
  111. unsigned head;
  112. unsigned index;
  113. void *datap;
  114. #ifdef RING_POLL
  115. head = (ring_size - 1) & guest.last_used_idx;
  116. index = ring.used->ring[head].id;
  117. if ((index ^ guest.last_used_idx ^ 0x8000) & ~(ring_size - 1))
  118. return NULL;
  119. /* Barrier B (for pairing) */
  120. smp_acquire();
  121. index &= ring_size - 1;
  122. #else
  123. if (ring.used->idx == guest.last_used_idx)
  124. return NULL;
  125. /* Barrier B (for pairing) */
  126. smp_acquire();
  127. head = (ring_size - 1) & guest.last_used_idx;
  128. index = ring.used->ring[head].id;
  129. #endif
  130. *lenp = ring.used->ring[head].len;
  131. datap = data[index].data;
  132. *bufp = (void*)(unsigned long)ring.desc[index].addr;
  133. data[index].data = NULL;
  134. ring.desc[index].next = guest.free_head;
  135. guest.free_head = index;
  136. guest.num_free++;
  137. guest.last_used_idx++;
  138. return datap;
  139. }
  140. void poll_used(void)
  141. {
  142. #ifdef RING_POLL
  143. unsigned head = (ring_size - 1) & guest.last_used_idx;
  144. for (;;) {
  145. unsigned index = ring.used->ring[head].id;
  146. if ((index ^ guest.last_used_idx ^ 0x8000) & ~(ring_size - 1))
  147. busy_wait();
  148. else
  149. break;
  150. }
  151. #else
  152. unsigned head = guest.last_used_idx;
  153. while (ring.used->idx == head)
  154. busy_wait();
  155. #endif
  156. }
  157. void disable_call()
  158. {
  159. /* Doing nothing to disable calls might cause
  160. * extra interrupts, but reduces the number of cache misses.
  161. */
  162. }
  163. bool enable_call()
  164. {
  165. unsigned short last_used_idx;
  166. vring_used_event(&ring) = (last_used_idx = guest.last_used_idx);
  167. /* Flush call index write */
  168. /* Barrier D (for pairing) */
  169. smp_mb();
  170. #ifdef RING_POLL
  171. {
  172. unsigned short head = last_used_idx & (ring_size - 1);
  173. unsigned index = ring.used->ring[head].id;
  174. return (index ^ last_used_idx ^ 0x8000) & ~(ring_size - 1);
  175. }
  176. #else
  177. return ring.used->idx == last_used_idx;
  178. #endif
  179. }
  180. void kick_available(void)
  181. {
  182. /* Flush in previous flags write */
  183. /* Barrier C (for pairing) */
  184. smp_mb();
  185. if (!vring_need_event(vring_avail_event(&ring),
  186. guest.avail_idx,
  187. guest.kicked_avail_idx))
  188. return;
  189. guest.kicked_avail_idx = guest.avail_idx;
  190. kick();
  191. }
  192. /* host side */
  193. void disable_kick()
  194. {
  195. /* Doing nothing to disable kicks might cause
  196. * extra interrupts, but reduces the number of cache misses.
  197. */
  198. }
  199. bool enable_kick()
  200. {
  201. unsigned head = host.used_idx;
  202. vring_avail_event(&ring) = head;
  203. /* Barrier C (for pairing) */
  204. smp_mb();
  205. #ifdef RING_POLL
  206. {
  207. unsigned index = ring.avail->ring[head & (ring_size - 1)];
  208. return (index ^ head ^ 0x8000) & ~(ring_size - 1);
  209. }
  210. #else
  211. return head == ring.avail->idx;
  212. #endif
  213. }
  214. void poll_avail(void)
  215. {
  216. unsigned head = host.used_idx;
  217. #ifdef RING_POLL
  218. for (;;) {
  219. unsigned index = ring.avail->ring[head & (ring_size - 1)];
  220. if ((index ^ head ^ 0x8000) & ~(ring_size - 1))
  221. busy_wait();
  222. else
  223. break;
  224. }
  225. #else
  226. while (ring.avail->idx == head)
  227. busy_wait();
  228. #endif
  229. }
  230. bool use_buf(unsigned *lenp, void **bufp)
  231. {
  232. unsigned used_idx = host.used_idx;
  233. struct vring_desc *desc;
  234. unsigned head;
  235. #ifdef RING_POLL
  236. head = ring.avail->ring[used_idx & (ring_size - 1)];
  237. if ((used_idx ^ head ^ 0x8000) & ~(ring_size - 1))
  238. return false;
  239. /* Barrier A (for pairing) */
  240. smp_acquire();
  241. used_idx &= ring_size - 1;
  242. desc = &ring.desc[head & (ring_size - 1)];
  243. #else
  244. if (used_idx == ring.avail->idx)
  245. return false;
  246. /* Barrier A (for pairing) */
  247. smp_acquire();
  248. used_idx &= ring_size - 1;
  249. head = ring.avail->ring[used_idx];
  250. desc = &ring.desc[head];
  251. #endif
  252. *lenp = desc->len;
  253. *bufp = (void *)(unsigned long)desc->addr;
  254. /* now update used ring */
  255. ring.used->ring[used_idx].id = head;
  256. ring.used->ring[used_idx].len = desc->len - 1;
  257. /* Barrier B (for pairing) */
  258. smp_release();
  259. host.used_idx++;
  260. ring.used->idx = host.used_idx;
  261. return true;
  262. }
  263. void call_used(void)
  264. {
  265. /* Flush in previous flags write */
  266. /* Barrier D (for pairing) */
  267. smp_mb();
  268. if (!vring_need_event(vring_used_event(&ring),
  269. host.used_idx,
  270. host.called_used_idx))
  271. return;
  272. host.called_used_idx = host.used_idx;
  273. call();
  274. }