virtio-iommu.c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. /*
  2. * libqos driver virtio-iommu-pci framework
  3. *
  4. * Copyright (c) 2021 Red Hat, Inc.
  5. *
  6. * Authors:
  7. * Eric Auger <eric.auger@redhat.com>
  8. *
  9. * This work is licensed under the terms of the GNU GPL, version 2 or (at your
  10. * option) any later version. See the COPYING file in the top-level directory.
  11. *
  12. */
  13. #include "qemu/osdep.h"
  14. #include "../libqtest.h"
  15. #include "qemu/module.h"
  16. #include "qgraph.h"
  17. #include "virtio-iommu.h"
  18. #include "hw/virtio/virtio-iommu.h"
  19. static QGuestAllocator *alloc;
  20. /* virtio-iommu-device */
  21. static void *qvirtio_iommu_get_driver(QVirtioIOMMU *v_iommu,
  22. const char *interface)
  23. {
  24. if (!g_strcmp0(interface, "virtio-iommu")) {
  25. return v_iommu;
  26. }
  27. if (!g_strcmp0(interface, "virtio")) {
  28. return v_iommu->vdev;
  29. }
  30. fprintf(stderr, "%s not present in virtio-iommu-device\n", interface);
  31. g_assert_not_reached();
  32. }
  33. static void virtio_iommu_cleanup(QVirtioIOMMU *interface)
  34. {
  35. qvirtqueue_cleanup(interface->vdev->bus, interface->vq, alloc);
  36. }
  37. static void virtio_iommu_setup(QVirtioIOMMU *interface)
  38. {
  39. QVirtioDevice *vdev = interface->vdev;
  40. uint64_t features;
  41. features = qvirtio_get_features(vdev);
  42. features &= ~(QVIRTIO_F_BAD_FEATURE |
  43. (1ull << VIRTIO_RING_F_INDIRECT_DESC) |
  44. (1ull << VIRTIO_RING_F_EVENT_IDX) |
  45. (1ull << VIRTIO_IOMMU_F_BYPASS));
  46. qvirtio_set_features(vdev, features);
  47. interface->vq = qvirtqueue_setup(interface->vdev, alloc, 0);
  48. qvirtio_set_driver_ok(interface->vdev);
  49. }
  50. /* virtio-iommu-pci */
  51. static void *qvirtio_iommu_pci_get_driver(void *object, const char *interface)
  52. {
  53. QVirtioIOMMUPCI *v_iommu = object;
  54. if (!g_strcmp0(interface, "pci-device")) {
  55. return v_iommu->pci_vdev.pdev;
  56. }
  57. return qvirtio_iommu_get_driver(&v_iommu->iommu, interface);
  58. }
  59. static void qvirtio_iommu_pci_destructor(QOSGraphObject *obj)
  60. {
  61. QVirtioIOMMUPCI *iommu_pci = (QVirtioIOMMUPCI *) obj;
  62. QVirtioIOMMU *interface = &iommu_pci->iommu;
  63. QOSGraphObject *pci_vobj = &iommu_pci->pci_vdev.obj;
  64. virtio_iommu_cleanup(interface);
  65. qvirtio_pci_destructor(pci_vobj);
  66. }
  67. static void qvirtio_iommu_pci_start_hw(QOSGraphObject *obj)
  68. {
  69. QVirtioIOMMUPCI *iommu_pci = (QVirtioIOMMUPCI *) obj;
  70. QVirtioIOMMU *interface = &iommu_pci->iommu;
  71. QOSGraphObject *pci_vobj = &iommu_pci->pci_vdev.obj;
  72. qvirtio_pci_start_hw(pci_vobj);
  73. virtio_iommu_setup(interface);
  74. }
  75. static void *virtio_iommu_pci_create(void *pci_bus, QGuestAllocator *t_alloc,
  76. void *addr)
  77. {
  78. QVirtioIOMMUPCI *virtio_rpci = g_new0(QVirtioIOMMUPCI, 1);
  79. QVirtioIOMMU *interface = &virtio_rpci->iommu;
  80. QOSGraphObject *obj = &virtio_rpci->pci_vdev.obj;
  81. virtio_pci_init(&virtio_rpci->pci_vdev, pci_bus, addr);
  82. interface->vdev = &virtio_rpci->pci_vdev.vdev;
  83. alloc = t_alloc;
  84. obj->get_driver = qvirtio_iommu_pci_get_driver;
  85. obj->start_hw = qvirtio_iommu_pci_start_hw;
  86. obj->destructor = qvirtio_iommu_pci_destructor;
  87. return obj;
  88. }
  89. static void virtio_iommu_register_nodes(void)
  90. {
  91. QPCIAddress addr = {
  92. .devfn = QPCI_DEVFN(4, 0),
  93. };
  94. QOSGraphEdgeOptions opts = {
  95. .extra_device_opts = "addr=04.0",
  96. };
  97. /* virtio-iommu-pci */
  98. add_qpci_address(&opts, &addr);
  99. qos_node_create_driver("virtio-iommu-pci", virtio_iommu_pci_create);
  100. qos_node_consumes("virtio-iommu-pci", "pci-bus", &opts);
  101. qos_node_produces("virtio-iommu-pci", "pci-device");
  102. qos_node_produces("virtio-iommu-pci", "virtio");
  103. qos_node_produces("virtio-iommu-pci", "virtio-iommu");
  104. }
  105. libqos_init(virtio_iommu_register_nodes);