aboutsummaryrefslogtreecommitdiff
path: root/memory.c
diff options
context:
space:
mode:
authorPeter Xu <peterx@redhat.com>2016-09-23 13:02:27 +0800
committerPaolo Bonzini <pbonzini@redhat.com>2016-09-27 09:00:04 +0200
commit5bf3d319030b1e95116ba49b31339f2bdd1d3b2a (patch)
treeb4d053cd9c0825b247957f30130e668d3965ac6c /memory.c
parentcdb3081269347fd9271fd1b7a9df312e2953bdd9 (diff)
memory: introduce IOMMUOps.notify_flag_changed
The new interface can be used to replace the old notify_started() and notify_stopped(). Meanwhile it provides explicit flags so that IOMMUs can know what kind of notifications it is requested for. Acked-by: David Gibson <david@gibson.dropbear.id.au> Signed-off-by: Peter Xu <peterx@redhat.com> Message-Id: <1474606948-14391-3-git-send-email-peterx@redhat.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Diffstat (limited to 'memory.c')
-rw-r--r--memory.c29
1 files changed, 21 insertions, 8 deletions
diff --git a/memory.c b/memory.c
index 69d9d9ab7f..27a3f2fca2 100644
--- a/memory.c
+++ b/memory.c
@@ -1414,6 +1414,7 @@ void memory_region_init_iommu(MemoryRegion *mr,
mr->iommu_ops = ops,
mr->terminates = true; /* then re-forwards */
QLIST_INIT(&mr->iommu_notify);
+ mr->iommu_notify_flags = IOMMU_NOTIFIER_NONE;
}
static void memory_region_finalize(Object *obj)
@@ -1508,16 +1509,31 @@ bool memory_region_is_logging(MemoryRegion *mr, uint8_t client)
return memory_region_get_dirty_log_mask(mr) & (1 << client);
}
+static void memory_region_update_iommu_notify_flags(MemoryRegion *mr)
+{
+ IOMMUNotifierFlag flags = IOMMU_NOTIFIER_NONE;
+ IOMMUNotifier *iommu_notifier;
+
+ QLIST_FOREACH(iommu_notifier, &mr->iommu_notify, node) {
+ flags |= iommu_notifier->notifier_flags;
+ }
+
+ if (flags != mr->iommu_notify_flags &&
+ mr->iommu_ops->notify_flag_changed) {
+ mr->iommu_ops->notify_flag_changed(mr, mr->iommu_notify_flags,
+ flags);
+ }
+
+ mr->iommu_notify_flags = flags;
+}
+
void memory_region_register_iommu_notifier(MemoryRegion *mr,
IOMMUNotifier *n)
{
/* We need to register for at least one bitfield */
assert(n->notifier_flags != IOMMU_NOTIFIER_NONE);
- if (mr->iommu_ops->notify_started &&
- QLIST_EMPTY(&mr->iommu_notify)) {
- mr->iommu_ops->notify_started(mr);
- }
QLIST_INSERT_HEAD(&mr->iommu_notify, n, node);
+ memory_region_update_iommu_notify_flags(mr);
}
uint64_t memory_region_iommu_get_min_page_size(MemoryRegion *mr)
@@ -1555,10 +1571,7 @@ void memory_region_unregister_iommu_notifier(MemoryRegion *mr,
IOMMUNotifier *n)
{
QLIST_REMOVE(n, node);
- if (mr->iommu_ops->notify_stopped &&
- QLIST_EMPTY(&mr->iommu_notify)) {
- mr->iommu_ops->notify_stopped(mr);
- }
+ memory_region_update_iommu_notify_flags(mr);
}
void memory_region_notify_iommu(MemoryRegion *mr,