@@ -455,7 +455,8 @@ static void vfio_listener_region_del(MemoryListener *listener,
QLIST_FOREACH(giommu, &container->giommu_list, giommu_next) {
if (giommu->iommu == section->mr) {
- memory_region_unregister_iommu_notifier(&giommu->n);
+ memory_region_unregister_iommu_notifier(giommu->iommu,
+ &giommu->n);
QLIST_REMOVE(giommu, giommu_next);
g_free(giommu);
break;
@@ -991,7 +992,7 @@ static void vfio_disconnect_container(VFIOGroup *group)
QLIST_REMOVE(container, next);
QLIST_FOREACH_SAFE(giommu, &container->giommu_list, giommu_next, tmp) {
- memory_region_unregister_iommu_notifier(&giommu->n);
+ memory_region_unregister_iommu_notifier(giommu->iommu, &giommu->n);
QLIST_REMOVE(giommu, giommu_next);
g_free(giommu);
}
@@ -153,6 +153,10 @@ struct MemoryRegionIOMMUOps {
IOMMUTLBEntry (*translate)(MemoryRegion *iommu, hwaddr addr, bool is_write);
/* Returns minimum supported page size */
uint64_t (*get_min_page_size)(MemoryRegion *iommu);
+ /* Called when the first notifier is set */
+ void (*notify_started)(MemoryRegion *iommu);
+ /* Called when the last notifier is removed */
+ void (*notify_stopped)(MemoryRegion *iommu);
};
typedef struct CoalescedMemoryRange CoalescedMemoryRange;
@@ -622,9 +626,11 @@ void memory_region_iommu_replay(MemoryRegion *mr, Notifier *n, bool is_write);
* memory_region_unregister_iommu_notifier: unregister a notifier for
* changes to IOMMU translation entries.
*
+ * @mr: the memory region which was observed and for which notity_stopped()
+ * needs to be called
* @n: the notifier to be removed.
*/
-void memory_region_unregister_iommu_notifier(Notifier *n);
+void memory_region_unregister_iommu_notifier(MemoryRegion *mr, Notifier *n);
/**
* memory_region_name: get a memory region's name
@@ -1499,6 +1499,10 @@ bool memory_region_is_logging(MemoryRegion *mr, uint8_t client)
void memory_region_register_iommu_notifier(MemoryRegion *mr, Notifier *n)
{
+ if (mr->iommu_ops->notify_started &&
+ QLIST_EMPTY(&mr->iommu_notify.notifiers)) {
+ mr->iommu_ops->notify_started(mr);
+ }
notifier_list_add(&mr->iommu_notify, n);
}
@@ -1532,9 +1536,13 @@ void memory_region_iommu_replay(MemoryRegion *mr, Notifier *n, bool is_write)
}
}
-void memory_region_unregister_iommu_notifier(Notifier *n)
+void memory_region_unregister_iommu_notifier(MemoryRegion *mr, Notifier *n)
{
notifier_remove(n);
+ if (mr->iommu_ops->notify_stopped &&
+ QLIST_EMPTY(&mr->iommu_notify.notifiers)) {
+ mr->iommu_ops->notify_stopped(mr);
+ }
}
void memory_region_notify_iommu(MemoryRegion *mr,