virtio-bus.c 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344
  1. /*
  2. * VirtioBus
  3. *
  4. * Copyright (C) 2012 : GreenSocs Ltd
  5. * http://www.greensocs.com/ , email: info@greensocs.com
  6. *
  7. * Developed by :
  8. * Frederic Konrad <fred.konrad@greensocs.com>
  9. *
  10. * This program is free software; you can redistribute it and/or modify
  11. * it under the terms of the GNU General Public License as published by
  12. * the Free Software Foundation, either version 2 of the License, or
  13. * (at your option) any later version.
  14. *
  15. * This program is distributed in the hope that it will be useful,
  16. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. * GNU General Public License for more details.
  19. *
  20. * You should have received a copy of the GNU General Public License along
  21. * with this program; if not, see <http://www.gnu.org/licenses/>.
  22. *
  23. */
  24. #include "qemu/osdep.h"
  25. #include "qemu/error-report.h"
  26. #include "qemu/module.h"
  27. #include "qapi/error.h"
  28. #include "hw/virtio/virtio-bus.h"
  29. #include "hw/virtio/virtio.h"
  30. #include "exec/address-spaces.h"
  31. /* #define DEBUG_VIRTIO_BUS */
  32. #ifdef DEBUG_VIRTIO_BUS
  33. #define DPRINTF(fmt, ...) \
  34. do { printf("virtio_bus: " fmt , ## __VA_ARGS__); } while (0)
  35. #else
  36. #define DPRINTF(fmt, ...) do { } while (0)
  37. #endif
  38. /* A VirtIODevice is being plugged */
  39. void virtio_bus_device_plugged(VirtIODevice *vdev, Error **errp)
  40. {
  41. DeviceState *qdev = DEVICE(vdev);
  42. BusState *qbus = BUS(qdev_get_parent_bus(qdev));
  43. VirtioBusState *bus = VIRTIO_BUS(qbus);
  44. VirtioBusClass *klass = VIRTIO_BUS_GET_CLASS(bus);
  45. VirtioDeviceClass *vdc = VIRTIO_DEVICE_GET_CLASS(vdev);
  46. bool has_iommu = virtio_host_has_feature(vdev, VIRTIO_F_IOMMU_PLATFORM);
  47. Error *local_err = NULL;
  48. DPRINTF("%s: plug device.\n", qbus->name);
  49. if (klass->pre_plugged != NULL) {
  50. klass->pre_plugged(qbus->parent, &local_err);
  51. if (local_err) {
  52. error_propagate(errp, local_err);
  53. return;
  54. }
  55. }
  56. /* Get the features of the plugged device. */
  57. assert(vdc->get_features != NULL);
  58. vdev->host_features = vdc->get_features(vdev, vdev->host_features,
  59. &local_err);
  60. if (local_err) {
  61. error_propagate(errp, local_err);
  62. return;
  63. }
  64. if (klass->device_plugged != NULL) {
  65. klass->device_plugged(qbus->parent, &local_err);
  66. }
  67. if (local_err) {
  68. error_propagate(errp, local_err);
  69. return;
  70. }
  71. if (klass->get_dma_as != NULL && has_iommu) {
  72. virtio_add_feature(&vdev->host_features, VIRTIO_F_IOMMU_PLATFORM);
  73. vdev->dma_as = klass->get_dma_as(qbus->parent);
  74. } else {
  75. vdev->dma_as = &address_space_memory;
  76. }
  77. }
  78. /* Reset the virtio_bus */
  79. void virtio_bus_reset(VirtioBusState *bus)
  80. {
  81. VirtIODevice *vdev = virtio_bus_get_device(bus);
  82. DPRINTF("%s: reset device.\n", BUS(bus)->name);
  83. if (vdev != NULL) {
  84. virtio_reset(vdev);
  85. }
  86. }
  87. /* A VirtIODevice is being unplugged */
  88. void virtio_bus_device_unplugged(VirtIODevice *vdev)
  89. {
  90. DeviceState *qdev = DEVICE(vdev);
  91. BusState *qbus = BUS(qdev_get_parent_bus(qdev));
  92. VirtioBusClass *klass = VIRTIO_BUS_GET_CLASS(qbus);
  93. DPRINTF("%s: remove device.\n", qbus->name);
  94. if (vdev != NULL) {
  95. if (klass->device_unplugged != NULL) {
  96. klass->device_unplugged(qbus->parent);
  97. }
  98. }
  99. }
  100. /* Get the device id of the plugged device. */
  101. uint16_t virtio_bus_get_vdev_id(VirtioBusState *bus)
  102. {
  103. VirtIODevice *vdev = virtio_bus_get_device(bus);
  104. assert(vdev != NULL);
  105. return vdev->device_id;
  106. }
  107. /* Get the config_len field of the plugged device. */
  108. size_t virtio_bus_get_vdev_config_len(VirtioBusState *bus)
  109. {
  110. VirtIODevice *vdev = virtio_bus_get_device(bus);
  111. assert(vdev != NULL);
  112. return vdev->config_len;
  113. }
  114. /* Get bad features of the plugged device. */
  115. uint32_t virtio_bus_get_vdev_bad_features(VirtioBusState *bus)
  116. {
  117. VirtIODevice *vdev = virtio_bus_get_device(bus);
  118. VirtioDeviceClass *k;
  119. assert(vdev != NULL);
  120. k = VIRTIO_DEVICE_GET_CLASS(vdev);
  121. if (k->bad_features != NULL) {
  122. return k->bad_features(vdev);
  123. } else {
  124. return 0;
  125. }
  126. }
  127. /* Get config of the plugged device. */
  128. void virtio_bus_get_vdev_config(VirtioBusState *bus, uint8_t *config)
  129. {
  130. VirtIODevice *vdev = virtio_bus_get_device(bus);
  131. VirtioDeviceClass *k;
  132. assert(vdev != NULL);
  133. k = VIRTIO_DEVICE_GET_CLASS(vdev);
  134. if (k->get_config != NULL) {
  135. k->get_config(vdev, config);
  136. }
  137. }
  138. /* Set config of the plugged device. */
  139. void virtio_bus_set_vdev_config(VirtioBusState *bus, uint8_t *config)
  140. {
  141. VirtIODevice *vdev = virtio_bus_get_device(bus);
  142. VirtioDeviceClass *k;
  143. assert(vdev != NULL);
  144. k = VIRTIO_DEVICE_GET_CLASS(vdev);
  145. if (k->set_config != NULL) {
  146. k->set_config(vdev, config);
  147. }
  148. }
  149. /* On success, ioeventfd ownership belongs to the caller. */
  150. int virtio_bus_grab_ioeventfd(VirtioBusState *bus)
  151. {
  152. VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(bus);
  153. /* vhost can be used even if ioeventfd=off in the proxy device,
  154. * so do not check k->ioeventfd_enabled.
  155. */
  156. if (!k->ioeventfd_assign) {
  157. return -ENOSYS;
  158. }
  159. if (bus->ioeventfd_grabbed == 0 && bus->ioeventfd_started) {
  160. virtio_bus_stop_ioeventfd(bus);
  161. /* Remember that we need to restart ioeventfd
  162. * when ioeventfd_grabbed becomes zero.
  163. */
  164. bus->ioeventfd_started = true;
  165. }
  166. bus->ioeventfd_grabbed++;
  167. return 0;
  168. }
  169. void virtio_bus_release_ioeventfd(VirtioBusState *bus)
  170. {
  171. assert(bus->ioeventfd_grabbed != 0);
  172. if (--bus->ioeventfd_grabbed == 0 && bus->ioeventfd_started) {
  173. /* Force virtio_bus_start_ioeventfd to act. */
  174. bus->ioeventfd_started = false;
  175. virtio_bus_start_ioeventfd(bus);
  176. }
  177. }
  178. int virtio_bus_start_ioeventfd(VirtioBusState *bus)
  179. {
  180. VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(bus);
  181. DeviceState *proxy = DEVICE(BUS(bus)->parent);
  182. VirtIODevice *vdev = virtio_bus_get_device(bus);
  183. VirtioDeviceClass *vdc = VIRTIO_DEVICE_GET_CLASS(vdev);
  184. int r;
  185. if (!k->ioeventfd_assign || !k->ioeventfd_enabled(proxy)) {
  186. return -ENOSYS;
  187. }
  188. if (bus->ioeventfd_started) {
  189. return 0;
  190. }
  191. /* Only set our notifier if we have ownership. */
  192. if (!bus->ioeventfd_grabbed) {
  193. r = vdc->start_ioeventfd(vdev);
  194. if (r < 0) {
  195. error_report("%s: failed. Fallback to userspace (slower).", __func__);
  196. return r;
  197. }
  198. }
  199. bus->ioeventfd_started = true;
  200. return 0;
  201. }
  202. void virtio_bus_stop_ioeventfd(VirtioBusState *bus)
  203. {
  204. VirtIODevice *vdev;
  205. VirtioDeviceClass *vdc;
  206. if (!bus->ioeventfd_started) {
  207. return;
  208. }
  209. /* Only remove our notifier if we have ownership. */
  210. if (!bus->ioeventfd_grabbed) {
  211. vdev = virtio_bus_get_device(bus);
  212. vdc = VIRTIO_DEVICE_GET_CLASS(vdev);
  213. vdc->stop_ioeventfd(vdev);
  214. }
  215. bus->ioeventfd_started = false;
  216. }
  217. bool virtio_bus_ioeventfd_enabled(VirtioBusState *bus)
  218. {
  219. VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(bus);
  220. DeviceState *proxy = DEVICE(BUS(bus)->parent);
  221. return k->ioeventfd_assign && k->ioeventfd_enabled(proxy);
  222. }
  223. /*
  224. * This function switches ioeventfd on/off in the device.
  225. * The caller must set or clear the handlers for the EventNotifier.
  226. */
  227. int virtio_bus_set_host_notifier(VirtioBusState *bus, int n, bool assign)
  228. {
  229. VirtIODevice *vdev = virtio_bus_get_device(bus);
  230. VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(bus);
  231. DeviceState *proxy = DEVICE(BUS(bus)->parent);
  232. VirtQueue *vq = virtio_get_queue(vdev, n);
  233. EventNotifier *notifier = virtio_queue_get_host_notifier(vq);
  234. int r = 0;
  235. if (!k->ioeventfd_assign) {
  236. return -ENOSYS;
  237. }
  238. if (assign) {
  239. r = event_notifier_init(notifier, 1);
  240. if (r < 0) {
  241. error_report("%s: unable to init event notifier: %s (%d)",
  242. __func__, strerror(-r), r);
  243. return r;
  244. }
  245. r = k->ioeventfd_assign(proxy, notifier, n, true);
  246. if (r < 0) {
  247. error_report("%s: unable to assign ioeventfd: %d", __func__, r);
  248. virtio_bus_cleanup_host_notifier(bus, n);
  249. }
  250. } else {
  251. k->ioeventfd_assign(proxy, notifier, n, false);
  252. }
  253. if (r == 0) {
  254. virtio_queue_set_host_notifier_enabled(vq, assign);
  255. }
  256. return r;
  257. }
  258. void virtio_bus_cleanup_host_notifier(VirtioBusState *bus, int n)
  259. {
  260. VirtIODevice *vdev = virtio_bus_get_device(bus);
  261. VirtQueue *vq = virtio_get_queue(vdev, n);
  262. EventNotifier *notifier = virtio_queue_get_host_notifier(vq);
  263. /* Test and clear notifier after disabling event,
  264. * in case poll callback didn't have time to run.
  265. */
  266. virtio_queue_host_notifier_read(notifier);
  267. event_notifier_cleanup(notifier);
  268. }
  269. static char *virtio_bus_get_dev_path(DeviceState *dev)
  270. {
  271. BusState *bus = qdev_get_parent_bus(dev);
  272. DeviceState *proxy = DEVICE(bus->parent);
  273. return qdev_get_dev_path(proxy);
  274. }
  275. static char *virtio_bus_get_fw_dev_path(DeviceState *dev)
  276. {
  277. return NULL;
  278. }
  279. static void virtio_bus_class_init(ObjectClass *klass, void *data)
  280. {
  281. BusClass *bus_class = BUS_CLASS(klass);
  282. bus_class->get_dev_path = virtio_bus_get_dev_path;
  283. bus_class->get_fw_dev_path = virtio_bus_get_fw_dev_path;
  284. }
  285. static const TypeInfo virtio_bus_info = {
  286. .name = TYPE_VIRTIO_BUS,
  287. .parent = TYPE_BUS,
  288. .instance_size = sizeof(VirtioBusState),
  289. .abstract = true,
  290. .class_size = sizeof(VirtioBusClass),
  291. .class_init = virtio_bus_class_init
  292. };
  293. static void virtio_register_types(void)
  294. {
  295. type_register_static(&virtio_bus_info);
  296. }
  297. type_init(virtio_register_types)