vhost-vsock-common.c 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258
  1. /*
  2. * Parent class for vhost-vsock devices
  3. *
  4. * Copyright 2015-2020 Red Hat, Inc.
  5. *
  6. * This work is licensed under the terms of the GNU GPL, version 2 or
  7. * (at your option) any later version. See the COPYING file in the
  8. * top-level directory.
  9. */
  10. #include "qemu/osdep.h"
  11. #include "standard-headers/linux/virtio_vsock.h"
  12. #include "qapi/error.h"
  13. #include "hw/virtio/virtio-access.h"
  14. #include "qemu/error-report.h"
  15. #include "hw/qdev-properties.h"
  16. #include "hw/virtio/vhost-vsock.h"
  17. #include "qemu/iov.h"
  18. #include "monitor/monitor.h"
  19. int vhost_vsock_common_start(VirtIODevice *vdev)
  20. {
  21. VHostVSockCommon *vvc = VHOST_VSOCK_COMMON(vdev);
  22. BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(vdev)));
  23. VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);
  24. int ret;
  25. int i;
  26. if (!k->set_guest_notifiers) {
  27. error_report("binding does not support guest notifiers");
  28. return -ENOSYS;
  29. }
  30. ret = vhost_dev_enable_notifiers(&vvc->vhost_dev, vdev);
  31. if (ret < 0) {
  32. error_report("Error enabling host notifiers: %d", -ret);
  33. return ret;
  34. }
  35. ret = k->set_guest_notifiers(qbus->parent, vvc->vhost_dev.nvqs, true);
  36. if (ret < 0) {
  37. error_report("Error binding guest notifier: %d", -ret);
  38. goto err_host_notifiers;
  39. }
  40. vvc->vhost_dev.acked_features = vdev->guest_features;
  41. ret = vhost_dev_start(&vvc->vhost_dev, vdev);
  42. if (ret < 0) {
  43. error_report("Error starting vhost: %d", -ret);
  44. goto err_guest_notifiers;
  45. }
  46. /*
  47. * guest_notifier_mask/pending not used yet, so just unmask
  48. * everything here. virtio-pci will do the right thing by
  49. * enabling/disabling irqfd.
  50. */
  51. for (i = 0; i < vvc->vhost_dev.nvqs; i++) {
  52. vhost_virtqueue_mask(&vvc->vhost_dev, vdev, i, false);
  53. }
  54. return 0;
  55. err_guest_notifiers:
  56. k->set_guest_notifiers(qbus->parent, vvc->vhost_dev.nvqs, false);
  57. err_host_notifiers:
  58. vhost_dev_disable_notifiers(&vvc->vhost_dev, vdev);
  59. return ret;
  60. }
  61. void vhost_vsock_common_stop(VirtIODevice *vdev)
  62. {
  63. VHostVSockCommon *vvc = VHOST_VSOCK_COMMON(vdev);
  64. BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(vdev)));
  65. VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);
  66. int ret;
  67. if (!k->set_guest_notifiers) {
  68. return;
  69. }
  70. vhost_dev_stop(&vvc->vhost_dev, vdev);
  71. ret = k->set_guest_notifiers(qbus->parent, vvc->vhost_dev.nvqs, false);
  72. if (ret < 0) {
  73. error_report("vhost guest notifier cleanup failed: %d", ret);
  74. return;
  75. }
  76. vhost_dev_disable_notifiers(&vvc->vhost_dev, vdev);
  77. }
  78. static void vhost_vsock_common_handle_output(VirtIODevice *vdev, VirtQueue *vq)
  79. {
  80. /* Do nothing */
  81. }
  82. static void vhost_vsock_common_guest_notifier_mask(VirtIODevice *vdev, int idx,
  83. bool mask)
  84. {
  85. VHostVSockCommon *vvc = VHOST_VSOCK_COMMON(vdev);
  86. vhost_virtqueue_mask(&vvc->vhost_dev, vdev, idx, mask);
  87. }
  88. static bool vhost_vsock_common_guest_notifier_pending(VirtIODevice *vdev,
  89. int idx)
  90. {
  91. VHostVSockCommon *vvc = VHOST_VSOCK_COMMON(vdev);
  92. return vhost_virtqueue_pending(&vvc->vhost_dev, idx);
  93. }
  94. static void vhost_vsock_common_send_transport_reset(VHostVSockCommon *vvc)
  95. {
  96. VirtQueueElement *elem;
  97. VirtQueue *vq = vvc->event_vq;
  98. struct virtio_vsock_event event = {
  99. .id = cpu_to_le32(VIRTIO_VSOCK_EVENT_TRANSPORT_RESET),
  100. };
  101. elem = virtqueue_pop(vq, sizeof(VirtQueueElement));
  102. if (!elem) {
  103. error_report("vhost-vsock missed transport reset event");
  104. return;
  105. }
  106. if (elem->out_num) {
  107. error_report("invalid vhost-vsock event virtqueue element with "
  108. "out buffers");
  109. goto out;
  110. }
  111. if (iov_from_buf(elem->in_sg, elem->in_num, 0,
  112. &event, sizeof(event)) != sizeof(event)) {
  113. error_report("vhost-vsock event virtqueue element is too short");
  114. goto out;
  115. }
  116. virtqueue_push(vq, elem, sizeof(event));
  117. virtio_notify(VIRTIO_DEVICE(vvc), vq);
  118. out:
  119. g_free(elem);
  120. }
  121. static void vhost_vsock_common_post_load_timer_cleanup(VHostVSockCommon *vvc)
  122. {
  123. if (!vvc->post_load_timer) {
  124. return;
  125. }
  126. timer_del(vvc->post_load_timer);
  127. timer_free(vvc->post_load_timer);
  128. vvc->post_load_timer = NULL;
  129. }
  130. static void vhost_vsock_common_post_load_timer_cb(void *opaque)
  131. {
  132. VHostVSockCommon *vvc = opaque;
  133. vhost_vsock_common_post_load_timer_cleanup(vvc);
  134. vhost_vsock_common_send_transport_reset(vvc);
  135. }
  136. int vhost_vsock_common_pre_save(void *opaque)
  137. {
  138. VHostVSockCommon *vvc = opaque;
  139. /*
  140. * At this point, backend must be stopped, otherwise
  141. * it might keep writing to memory.
  142. */
  143. assert(!vvc->vhost_dev.started);
  144. return 0;
  145. }
  146. int vhost_vsock_common_post_load(void *opaque, int version_id)
  147. {
  148. VHostVSockCommon *vvc = opaque;
  149. VirtIODevice *vdev = VIRTIO_DEVICE(vvc);
  150. if (virtio_queue_get_addr(vdev, 2)) {
  151. /*
  152. * Defer transport reset event to a vm clock timer so that virtqueue
  153. * changes happen after migration has completed.
  154. */
  155. assert(!vvc->post_load_timer);
  156. vvc->post_load_timer =
  157. timer_new_ns(QEMU_CLOCK_VIRTUAL,
  158. vhost_vsock_common_post_load_timer_cb,
  159. vvc);
  160. timer_mod(vvc->post_load_timer, 1);
  161. }
  162. return 0;
  163. }
  164. void vhost_vsock_common_realize(VirtIODevice *vdev, const char *name)
  165. {
  166. VHostVSockCommon *vvc = VHOST_VSOCK_COMMON(vdev);
  167. virtio_init(vdev, name, VIRTIO_ID_VSOCK,
  168. sizeof(struct virtio_vsock_config));
  169. /* Receive and transmit queues belong to vhost */
  170. vvc->recv_vq = virtio_add_queue(vdev, VHOST_VSOCK_QUEUE_SIZE,
  171. vhost_vsock_common_handle_output);
  172. vvc->trans_vq = virtio_add_queue(vdev, VHOST_VSOCK_QUEUE_SIZE,
  173. vhost_vsock_common_handle_output);
  174. /* The event queue belongs to QEMU */
  175. vvc->event_vq = virtio_add_queue(vdev, VHOST_VSOCK_QUEUE_SIZE,
  176. vhost_vsock_common_handle_output);
  177. vvc->vhost_dev.nvqs = ARRAY_SIZE(vvc->vhost_vqs);
  178. vvc->vhost_dev.vqs = vvc->vhost_vqs;
  179. vvc->post_load_timer = NULL;
  180. }
  181. void vhost_vsock_common_unrealize(VirtIODevice *vdev)
  182. {
  183. VHostVSockCommon *vvc = VHOST_VSOCK_COMMON(vdev);
  184. vhost_vsock_common_post_load_timer_cleanup(vvc);
  185. virtio_delete_queue(vvc->recv_vq);
  186. virtio_delete_queue(vvc->trans_vq);
  187. virtio_delete_queue(vvc->event_vq);
  188. virtio_cleanup(vdev);
  189. }
  190. static void vhost_vsock_common_class_init(ObjectClass *klass, void *data)
  191. {
  192. DeviceClass *dc = DEVICE_CLASS(klass);
  193. VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
  194. set_bit(DEVICE_CATEGORY_MISC, dc->categories);
  195. vdc->guest_notifier_mask = vhost_vsock_common_guest_notifier_mask;
  196. vdc->guest_notifier_pending = vhost_vsock_common_guest_notifier_pending;
  197. }
  198. static const TypeInfo vhost_vsock_common_info = {
  199. .name = TYPE_VHOST_VSOCK_COMMON,
  200. .parent = TYPE_VIRTIO_DEVICE,
  201. .instance_size = sizeof(VHostVSockCommon),
  202. .class_init = vhost_vsock_common_class_init,
  203. .abstract = true,
  204. };
  205. static void vhost_vsock_common_register_types(void)
  206. {
  207. type_register_static(&vhost_vsock_common_info);
  208. }
  209. type_init(vhost_vsock_common_register_types)