For virtio-iommu, on replay first unmap any previous iommu-mapping and then map in iommu as per guest iommu mappings.
Also if virtual iommu do have it own replay then memory_region_iommu_replay() calls "imrc->translate()", While virtio-iommu translate() expects device to be registered before it is called. So having replay of virtio-iommu helps to take no action if device not yet probed/attached. Signed-off-by: Bharat Bhushan <bharat.bhus...@nxp.com> --- v4->v5: - Rebase to v9 version from Eric (no change) hw/virtio/trace-events | 1 + hw/virtio/virtio-iommu.c | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/hw/virtio/trace-events b/hw/virtio/trace-events index 420b1e471b..f29a027258 100644 --- a/hw/virtio/trace-events +++ b/hw/virtio/trace-events @@ -74,3 +74,4 @@ virtio_iommu_fill_none_property(uint32_t devid) "devid=%d" virtio_iommu_report_fault(uint8_t reason, uint32_t flags, uint32_t endpoint, uint64_t addr) "FAULT reason=%d flags=%d endpoint=%d address =0x%"PRIx64 virtio_iommu_notify_map(const char *name, uint64_t iova, uint64_t paddr, uint64_t map_size) "mr=%s iova=0x%"PRIx64" pa=0x%" PRIx64" size=0x%"PRIx64"" virtio_iommu_notify_unmap(const char *name, uint64_t iova, uint64_t map_size) "mr=%s iova=0x%"PRIx64" size=0x%"PRIx64"" +virtio_iommu_remap(uint64_t iova, uint64_t pa, uint64_t size) "iova=0x%"PRIx64" pa=0x%" PRIx64" size=0x%"PRIx64"" diff --git a/hw/virtio/virtio-iommu.c b/hw/virtio/virtio-iommu.c index 7e8149e719..c9d8b3aa4c 100644 --- a/hw/virtio/virtio-iommu.c +++ b/hw/virtio/virtio-iommu.c @@ -1015,6 +1015,43 @@ static gint int_cmp(gconstpointer a, gconstpointer b, gpointer user_data) return (ua > ub) - (ua < ub); } +static gboolean virtio_iommu_remap(gpointer key, gpointer value, gpointer data) +{ + viommu_mapping *mapping = (viommu_mapping *) value; + IOMMUMemoryRegion *mr = (IOMMUMemoryRegion *) data; + + trace_virtio_iommu_remap(mapping->virt_addr, mapping->phys_addr, + mapping->size); + /* unmap previous entry and map again */ + virtio_iommu_notify_unmap(mr, mapping->virt_addr, mapping->size); + + virtio_iommu_notify_map(mr, mapping->virt_addr, mapping->phys_addr, + mapping->size); + return false; +} + +static void virtio_iommu_replay(IOMMUMemoryRegion *mr, IOMMUNotifier *n) +{ + IOMMUDevice *sdev = container_of(mr, IOMMUDevice, iommu_mr); + VirtIOIOMMU *s = sdev->viommu; + uint32_t sid; + viommu_endpoint *ep; + + sid = virtio_iommu_get_sid(sdev); + + qemu_mutex_lock(&s->mutex); + + ep = g_tree_lookup(s->endpoints, GUINT_TO_POINTER(sid)); + if (!ep || !ep->domain) { + goto unlock; + } + + g_tree_foreach(ep->domain->mappings, virtio_iommu_remap, mr); + +unlock: + qemu_mutex_unlock(&s->mutex); +} + static void virtio_iommu_device_realize(DeviceState *dev, Error **errp) { VirtIODevice *vdev = VIRTIO_DEVICE(dev); @@ -1129,6 +1166,7 @@ static void virtio_iommu_memory_region_class_init(ObjectClass *klass, IOMMUMemoryRegionClass *imrc = IOMMU_MEMORY_REGION_CLASS(klass); imrc->translate = virtio_iommu_translate; + imrc->replay = virtio_iommu_replay; } static const TypeInfo virtio_iommu_info = { -- 2.19.1