container-base.c 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. /*
  2. * VFIO BASE CONTAINER
  3. *
  4. * Copyright (C) 2023 Intel Corporation.
  5. * Copyright Red Hat, Inc. 2023
  6. *
  7. * Authors: Yi Liu <yi.l.liu@intel.com>
  8. * Eric Auger <eric.auger@redhat.com>
  9. *
  10. * SPDX-License-Identifier: GPL-2.0-or-later
  11. */
  12. #include "qemu/osdep.h"
  13. #include "qapi/error.h"
  14. #include "qemu/error-report.h"
  15. #include "hw/vfio/vfio-container-base.h"
  16. int vfio_container_dma_map(VFIOContainerBase *bcontainer,
  17. hwaddr iova, ram_addr_t size,
  18. void *vaddr, bool readonly)
  19. {
  20. VFIOIOMMUClass *vioc = VFIO_IOMMU_GET_CLASS(bcontainer);
  21. g_assert(vioc->dma_map);
  22. return vioc->dma_map(bcontainer, iova, size, vaddr, readonly);
  23. }
  24. int vfio_container_dma_unmap(VFIOContainerBase *bcontainer,
  25. hwaddr iova, ram_addr_t size,
  26. IOMMUTLBEntry *iotlb)
  27. {
  28. VFIOIOMMUClass *vioc = VFIO_IOMMU_GET_CLASS(bcontainer);
  29. g_assert(vioc->dma_unmap);
  30. return vioc->dma_unmap(bcontainer, iova, size, iotlb);
  31. }
  32. bool vfio_container_add_section_window(VFIOContainerBase *bcontainer,
  33. MemoryRegionSection *section,
  34. Error **errp)
  35. {
  36. VFIOIOMMUClass *vioc = VFIO_IOMMU_GET_CLASS(bcontainer);
  37. if (!vioc->add_window) {
  38. return true;
  39. }
  40. return vioc->add_window(bcontainer, section, errp);
  41. }
  42. void vfio_container_del_section_window(VFIOContainerBase *bcontainer,
  43. MemoryRegionSection *section)
  44. {
  45. VFIOIOMMUClass *vioc = VFIO_IOMMU_GET_CLASS(bcontainer);
  46. if (!vioc->del_window) {
  47. return;
  48. }
  49. return vioc->del_window(bcontainer, section);
  50. }
  51. int vfio_container_set_dirty_page_tracking(VFIOContainerBase *bcontainer,
  52. bool start, Error **errp)
  53. {
  54. VFIOIOMMUClass *vioc = VFIO_IOMMU_GET_CLASS(bcontainer);
  55. int ret;
  56. if (!bcontainer->dirty_pages_supported) {
  57. return 0;
  58. }
  59. g_assert(vioc->set_dirty_page_tracking);
  60. if (bcontainer->dirty_pages_started == start) {
  61. return 0;
  62. }
  63. ret = vioc->set_dirty_page_tracking(bcontainer, start, errp);
  64. if (!ret) {
  65. bcontainer->dirty_pages_started = start;
  66. }
  67. return ret;
  68. }
  69. int vfio_container_query_dirty_bitmap(const VFIOContainerBase *bcontainer,
  70. VFIOBitmap *vbmap, hwaddr iova, hwaddr size, Error **errp)
  71. {
  72. VFIOIOMMUClass *vioc = VFIO_IOMMU_GET_CLASS(bcontainer);
  73. g_assert(vioc->query_dirty_bitmap);
  74. return vioc->query_dirty_bitmap(bcontainer, vbmap, iova, size,
  75. errp);
  76. }
  77. static gpointer copy_iova_range(gconstpointer src, gpointer data)
  78. {
  79. Range *source = (Range *)src;
  80. Range *dest = g_new(Range, 1);
  81. range_set_bounds(dest, range_lob(source), range_upb(source));
  82. return dest;
  83. }
  84. GList *vfio_container_get_iova_ranges(const VFIOContainerBase *bcontainer)
  85. {
  86. assert(bcontainer);
  87. return g_list_copy_deep(bcontainer->iova_ranges, copy_iova_range, NULL);
  88. }
  89. static void vfio_container_instance_finalize(Object *obj)
  90. {
  91. VFIOContainerBase *bcontainer = VFIO_IOMMU(obj);
  92. VFIOGuestIOMMU *giommu, *tmp;
  93. QLIST_SAFE_REMOVE(bcontainer, next);
  94. QLIST_FOREACH_SAFE(giommu, &bcontainer->giommu_list, giommu_next, tmp) {
  95. memory_region_unregister_iommu_notifier(
  96. MEMORY_REGION(giommu->iommu_mr), &giommu->n);
  97. QLIST_REMOVE(giommu, giommu_next);
  98. g_free(giommu);
  99. }
  100. g_list_free_full(bcontainer->iova_ranges, g_free);
  101. }
  102. static void vfio_container_instance_init(Object *obj)
  103. {
  104. VFIOContainerBase *bcontainer = VFIO_IOMMU(obj);
  105. bcontainer->error = NULL;
  106. bcontainer->dirty_pages_supported = false;
  107. bcontainer->dma_max_mappings = 0;
  108. bcontainer->iova_ranges = NULL;
  109. QLIST_INIT(&bcontainer->giommu_list);
  110. QLIST_INIT(&bcontainer->vrdl_list);
  111. }
  112. static const TypeInfo types[] = {
  113. {
  114. .name = TYPE_VFIO_IOMMU,
  115. .parent = TYPE_OBJECT,
  116. .instance_init = vfio_container_instance_init,
  117. .instance_finalize = vfio_container_instance_finalize,
  118. .instance_size = sizeof(VFIOContainerBase),
  119. .class_size = sizeof(VFIOIOMMUClass),
  120. .abstract = true,
  121. },
  122. };
  123. DEFINE_TYPES(types)