summaryrefslogtreecommitdiff
path: root/include/exec
diff options
context:
space:
mode:
authorPeter Xu <peterx@redhat.com>2016-09-23 13:02:26 +0800
committerPaolo Bonzini <pbonzini@redhat.com>2016-09-27 08:59:16 +0200
commitcdb3081269347fd9271fd1b7a9df312e2953bdd9 (patch)
treeb9eb019b24ce2ebd5c849f513975960ed4c2abfd /include/exec
parent7cfdc02dae0d2ff58c897496cfdbbafc0eda0f3f (diff)
downloadqemu-cdb3081269347fd9271fd1b7a9df312e2953bdd9.zip
memory: introduce IOMMUNotifier and its caps
IOMMU Notifier list is used for notifying IO address mapping changes. Currently VFIO is the only user. However it is possible that future consumer like vhost would like to only listen to part of its notifications (e.g., cache invalidations). This patch introduced IOMMUNotifier and IOMMUNotfierFlag bits for a finer grained control of it. IOMMUNotifier contains a bitfield for the notify consumer describing what kind of notification it is interested in. Currently two kinds of notifications are defined: - IOMMU_NOTIFIER_MAP: for newly mapped entries (additions) - IOMMU_NOTIFIER_UNMAP: for entries to be removed (cache invalidates) When registering the IOMMU notifier, we need to specify one or multiple types of messages to listen to. When notifications are triggered, its type will be checked against the notifier's type bits, and only notifiers with registered bits will be notified. (For any IOMMU implementation, an in-place mapping change should be notified with an UNMAP followed by a MAP.) Signed-off-by: Peter Xu <peterx@redhat.com> Message-Id: <1474606948-14391-2-git-send-email-peterx@redhat.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Diffstat (limited to 'include/exec')
-rw-r--r--include/exec/memory.h47
1 files changed, 40 insertions, 7 deletions
diff --git a/include/exec/memory.h b/include/exec/memory.h
index 3e4d4164cd..14cda673f9 100644
--- a/include/exec/memory.h
+++ b/include/exec/memory.h
@@ -67,6 +67,27 @@ struct IOMMUTLBEntry {
IOMMUAccessFlags perm;
};
+/*
+ * Bitmap for different IOMMUNotifier capabilities. Each notifier can
+ * register with one or multiple IOMMU Notifier capability bit(s).
+ */
+typedef enum {
+ IOMMU_NOTIFIER_NONE = 0,
+ /* Notify cache invalidations */
+ IOMMU_NOTIFIER_UNMAP = 0x1,
+ /* Notify entry changes (newly created entries) */
+ IOMMU_NOTIFIER_MAP = 0x2,
+} IOMMUNotifierFlag;
+
+#define IOMMU_NOTIFIER_ALL (IOMMU_NOTIFIER_MAP | IOMMU_NOTIFIER_UNMAP)
+
+struct IOMMUNotifier {
+ void (*notify)(struct IOMMUNotifier *notifier, IOMMUTLBEntry *data);
+ IOMMUNotifierFlag notifier_flags;
+ QLIST_ENTRY(IOMMUNotifier) node;
+};
+typedef struct IOMMUNotifier IOMMUNotifier;
+
/* New-style MMIO accessors can indicate that the transaction failed.
* A zero (MEMTX_OK) response means success; anything else is a failure
* of some kind. The memory subsystem will bitwise-OR together results
@@ -201,7 +222,7 @@ struct MemoryRegion {
const char *name;
unsigned ioeventfd_nb;
MemoryRegionIoeventfd *ioeventfds;
- NotifierList iommu_notify;
+ QLIST_HEAD(, IOMMUNotifier) iommu_notify;
};
/**
@@ -607,6 +628,15 @@ uint64_t memory_region_iommu_get_min_page_size(MemoryRegion *mr);
/**
* memory_region_notify_iommu: notify a change in an IOMMU translation entry.
*
+ * The notification type will be decided by entry.perm bits:
+ *
+ * - For UNMAP (cache invalidation) notifies: set entry.perm to IOMMU_NONE.
+ * - For MAP (newly added entry) notifies: set entry.perm to the
+ * permission of the page (which is definitely !IOMMU_NONE).
+ *
+ * Note: for any IOMMU implementation, an in-place mapping change
+ * should be notified with an UNMAP followed by a MAP.
+ *
* @mr: the memory region that was changed
* @entry: the new entry in the IOMMU translation table. The entry
* replaces all old entries for the same virtual I/O address range.
@@ -620,11 +650,12 @@ void memory_region_notify_iommu(MemoryRegion *mr,
* IOMMU translation entries.
*
* @mr: the memory region to observe
- * @n: the notifier to be added; the notifier receives a pointer to an
- * #IOMMUTLBEntry as the opaque value; the pointer ceases to be
- * valid on exit from the notifier.
+ * @n: the IOMMUNotifier to be added; the notify callback receives a
+ * pointer to an #IOMMUTLBEntry as the opaque value; the pointer
+ * ceases to be valid on exit from the notifier.
*/
-void memory_region_register_iommu_notifier(MemoryRegion *mr, Notifier *n);
+void memory_region_register_iommu_notifier(MemoryRegion *mr,
+ IOMMUNotifier *n);
/**
* memory_region_iommu_replay: replay existing IOMMU translations to
@@ -636,7 +667,8 @@ void memory_region_register_iommu_notifier(MemoryRegion *mr, Notifier *n);
* @is_write: Whether to treat the replay as a translate "write"
* through the iommu
*/
-void memory_region_iommu_replay(MemoryRegion *mr, Notifier *n, bool is_write);
+void memory_region_iommu_replay(MemoryRegion *mr, IOMMUNotifier *n,
+ bool is_write);
/**
* memory_region_unregister_iommu_notifier: unregister a notifier for
@@ -646,7 +678,8 @@ void memory_region_iommu_replay(MemoryRegion *mr, Notifier *n, bool is_write);
* needs to be called
* @n: the notifier to be removed.
*/
-void memory_region_unregister_iommu_notifier(MemoryRegion *mr, Notifier *n);
+void memory_region_unregister_iommu_notifier(MemoryRegion *mr,
+ IOMMUNotifier *n);
/**
* memory_region_name: get a memory region's name