virtio_ring_0_9.c 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334
  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. /* enabling the below activates experimental in-order code
  27. * (which skips ring updates and reads and writes len in descriptor).
  28. */
  29. /* #ifdef INORDER */
  30. #if defined(RING_POLL) && defined(INORDER)
  31. #error "RING_POLL and INORDER are mutually exclusive"
  32. #endif
  33. /* how much padding is needed to avoid false cache sharing */
  34. #define HOST_GUEST_PADDING 0x80
  35. struct guest {
  36. unsigned short avail_idx;
  37. unsigned short last_used_idx;
  38. unsigned short num_free;
  39. unsigned short kicked_avail_idx;
  40. #ifndef INORDER
  41. unsigned short free_head;
  42. #else
  43. unsigned short reserved_free_head;
  44. #endif
  45. unsigned char reserved[HOST_GUEST_PADDING - 10];
  46. } guest;
  47. struct host {
  48. /* we do not need to track last avail index
  49. * unless we have more than one in flight.
  50. */
  51. unsigned short used_idx;
  52. unsigned short called_used_idx;
  53. unsigned char reserved[HOST_GUEST_PADDING - 4];
  54. } host;
  55. /* implemented by ring */
  56. void alloc_ring(void)
  57. {
  58. int ret;
  59. int i;
  60. void *p;
  61. ret = posix_memalign(&p, 0x1000, vring_size(ring_size, 0x1000));
  62. if (ret) {
  63. perror("Unable to allocate ring buffer.\n");
  64. exit(3);
  65. }
  66. memset(p, 0, vring_size(ring_size, 0x1000));
  67. vring_init(&ring, ring_size, p, 0x1000);
  68. guest.avail_idx = 0;
  69. guest.kicked_avail_idx = -1;
  70. guest.last_used_idx = 0;
  71. #ifndef INORDER
  72. /* Put everything in free lists. */
  73. guest.free_head = 0;
  74. #endif
  75. for (i = 0; i < ring_size - 1; i++)
  76. ring.desc[i].next = i + 1;
  77. host.used_idx = 0;
  78. host.called_used_idx = -1;
  79. guest.num_free = ring_size;
  80. data = malloc(ring_size * sizeof *data);
  81. if (!data) {
  82. perror("Unable to allocate data buffer.\n");
  83. exit(3);
  84. }
  85. memset(data, 0, ring_size * sizeof *data);
  86. }
  87. /* guest side */
  88. int add_inbuf(unsigned len, void *buf, void *datap)
  89. {
  90. unsigned head;
  91. #ifndef INORDER
  92. unsigned avail;
  93. #endif
  94. struct vring_desc *desc;
  95. if (!guest.num_free)
  96. return -1;
  97. #ifdef INORDER
  98. head = (ring_size - 1) & (guest.avail_idx++);
  99. #else
  100. head = guest.free_head;
  101. #endif
  102. guest.num_free--;
  103. desc = ring.desc;
  104. desc[head].flags = VRING_DESC_F_NEXT;
  105. desc[head].addr = (unsigned long)(void *)buf;
  106. desc[head].len = len;
  107. /* We do it like this to simulate the way
  108. * we'd have to flip it if we had multiple
  109. * descriptors.
  110. */
  111. desc[head].flags &= ~VRING_DESC_F_NEXT;
  112. #ifndef INORDER
  113. guest.free_head = desc[head].next;
  114. #endif
  115. data[head].data = datap;
  116. #ifdef RING_POLL
  117. /* Barrier A (for pairing) */
  118. smp_release();
  119. avail = guest.avail_idx++;
  120. ring.avail->ring[avail & (ring_size - 1)] =
  121. (head | (avail & ~(ring_size - 1))) ^ 0x8000;
  122. #else
  123. #ifndef INORDER
  124. /* Barrier A (for pairing) */
  125. smp_release();
  126. avail = (ring_size - 1) & (guest.avail_idx++);
  127. ring.avail->ring[avail] = head;
  128. #endif
  129. /* Barrier A (for pairing) */
  130. smp_release();
  131. #endif
  132. ring.avail->idx = guest.avail_idx;
  133. return 0;
  134. }
  135. void *get_buf(unsigned *lenp, void **bufp)
  136. {
  137. unsigned head;
  138. unsigned index;
  139. void *datap;
  140. #ifdef RING_POLL
  141. head = (ring_size - 1) & guest.last_used_idx;
  142. index = ring.used->ring[head].id;
  143. if ((index ^ guest.last_used_idx ^ 0x8000) & ~(ring_size - 1))
  144. return NULL;
  145. /* Barrier B (for pairing) */
  146. smp_acquire();
  147. index &= ring_size - 1;
  148. #else
  149. if (ring.used->idx == guest.last_used_idx)
  150. return NULL;
  151. /* Barrier B (for pairing) */
  152. smp_acquire();
  153. #ifdef INORDER
  154. head = (ring_size - 1) & guest.last_used_idx;
  155. index = head;
  156. #else
  157. head = (ring_size - 1) & guest.last_used_idx;
  158. index = ring.used->ring[head].id;
  159. #endif
  160. #endif
  161. #ifdef INORDER
  162. *lenp = ring.desc[index].len;
  163. #else
  164. *lenp = ring.used->ring[head].len;
  165. #endif
  166. datap = data[index].data;
  167. *bufp = (void*)(unsigned long)ring.desc[index].addr;
  168. data[index].data = NULL;
  169. #ifndef INORDER
  170. ring.desc[index].next = guest.free_head;
  171. guest.free_head = index;
  172. #endif
  173. guest.num_free++;
  174. guest.last_used_idx++;
  175. return datap;
  176. }
  177. bool used_empty()
  178. {
  179. unsigned short last_used_idx = guest.last_used_idx;
  180. #ifdef RING_POLL
  181. unsigned short head = last_used_idx & (ring_size - 1);
  182. unsigned index = ring.used->ring[head].id;
  183. return (index ^ last_used_idx ^ 0x8000) & ~(ring_size - 1);
  184. #else
  185. return ring.used->idx == last_used_idx;
  186. #endif
  187. }
  188. void disable_call()
  189. {
  190. /* Doing nothing to disable calls might cause
  191. * extra interrupts, but reduces the number of cache misses.
  192. */
  193. }
  194. bool enable_call()
  195. {
  196. vring_used_event(&ring) = guest.last_used_idx;
  197. /* Flush call index write */
  198. /* Barrier D (for pairing) */
  199. smp_mb();
  200. return used_empty();
  201. }
  202. void kick_available(void)
  203. {
  204. bool need;
  205. /* Flush in previous flags write */
  206. /* Barrier C (for pairing) */
  207. smp_mb();
  208. need = vring_need_event(vring_avail_event(&ring),
  209. guest.avail_idx,
  210. guest.kicked_avail_idx);
  211. guest.kicked_avail_idx = guest.avail_idx;
  212. if (need)
  213. kick();
  214. }
  215. /* host side */
  216. void disable_kick()
  217. {
  218. /* Doing nothing to disable kicks might cause
  219. * extra interrupts, but reduces the number of cache misses.
  220. */
  221. }
  222. bool enable_kick()
  223. {
  224. vring_avail_event(&ring) = host.used_idx;
  225. /* Barrier C (for pairing) */
  226. smp_mb();
  227. return avail_empty();
  228. }
  229. bool avail_empty()
  230. {
  231. unsigned head = host.used_idx;
  232. #ifdef RING_POLL
  233. unsigned index = ring.avail->ring[head & (ring_size - 1)];
  234. return ((index ^ head ^ 0x8000) & ~(ring_size - 1));
  235. #else
  236. return head == ring.avail->idx;
  237. #endif
  238. }
  239. bool use_buf(unsigned *lenp, void **bufp)
  240. {
  241. unsigned used_idx = host.used_idx;
  242. struct vring_desc *desc;
  243. unsigned head;
  244. #ifdef RING_POLL
  245. head = ring.avail->ring[used_idx & (ring_size - 1)];
  246. if ((used_idx ^ head ^ 0x8000) & ~(ring_size - 1))
  247. return false;
  248. /* Barrier A (for pairing) */
  249. smp_acquire();
  250. used_idx &= ring_size - 1;
  251. desc = &ring.desc[head & (ring_size - 1)];
  252. #else
  253. if (used_idx == ring.avail->idx)
  254. return false;
  255. /* Barrier A (for pairing) */
  256. smp_acquire();
  257. used_idx &= ring_size - 1;
  258. #ifdef INORDER
  259. head = used_idx;
  260. #else
  261. head = ring.avail->ring[used_idx];
  262. #endif
  263. desc = &ring.desc[head];
  264. #endif
  265. *lenp = desc->len;
  266. *bufp = (void *)(unsigned long)desc->addr;
  267. #ifdef INORDER
  268. desc->len = desc->len - 1;
  269. #else
  270. /* now update used ring */
  271. ring.used->ring[used_idx].id = head;
  272. ring.used->ring[used_idx].len = desc->len - 1;
  273. #endif
  274. /* Barrier B (for pairing) */
  275. smp_release();
  276. host.used_idx++;
  277. ring.used->idx = host.used_idx;
  278. return true;
  279. }
  280. void call_used(void)
  281. {
  282. bool need;
  283. /* Flush in previous flags write */
  284. /* Barrier D (for pairing) */
  285. smp_mb();
  286. need = vring_need_event(vring_used_event(&ring),
  287. host.used_idx,
  288. host.called_used_idx);
  289. host.called_used_idx = host.used_idx;
  290. if (need)
  291. call();
  292. }