mirror of
https://gitlab.com/qemu-project/qemu
synced 2024-11-05 20:35:44 +00:00
memory: introduce memory_region_notify_one()
Generalizing the notify logic in memory_region_notify_iommu() into a single function. This can be further used in customized replay() functions for IOMMUs. Reviewed-by: David Gibson <david@gibson.dropbear.id.au> Reviewed-by: Eric Auger <eric.auger@redhat.com> Reviewed-by: \"Michael S. Tsirkin\" <mst@redhat.com> Signed-off-by: Peter Xu <peterx@redhat.com> Message-Id: <1491562755-23867-5-git-send-email-peterx@redhat.com> Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
This commit is contained in:
parent
de472e4a92
commit
bd2bfa4c52
2 changed files with 39 additions and 16 deletions
|
@ -687,6 +687,21 @@ uint64_t memory_region_iommu_get_min_page_size(MemoryRegion *mr);
|
|||
void memory_region_notify_iommu(MemoryRegion *mr,
|
||||
IOMMUTLBEntry entry);
|
||||
|
||||
/**
|
||||
* memory_region_notify_one: notify a change in an IOMMU translation
|
||||
* entry to a single notifier
|
||||
*
|
||||
* This works just like memory_region_notify_iommu(), but it only
|
||||
* notifies a specific notifier, not all of them.
|
||||
*
|
||||
* @notifier: the notifier to be notified
|
||||
* @entry: the new entry in the IOMMU translation table. The entry
|
||||
* replaces all old entries for the same virtual I/O address range.
|
||||
* Deleted entries have .@perm == 0.
|
||||
*/
|
||||
void memory_region_notify_one(IOMMUNotifier *notifier,
|
||||
IOMMUTLBEntry *entry);
|
||||
|
||||
/**
|
||||
* memory_region_register_iommu_notifier: register a notifier for changes to
|
||||
* IOMMU translation entries.
|
||||
|
|
40
memory.c
40
memory.c
|
@ -1662,32 +1662,40 @@ void memory_region_unregister_iommu_notifier(MemoryRegion *mr,
|
|||
memory_region_update_iommu_notify_flags(mr);
|
||||
}
|
||||
|
||||
void memory_region_notify_iommu(MemoryRegion *mr,
|
||||
IOMMUTLBEntry entry)
|
||||
void memory_region_notify_one(IOMMUNotifier *notifier,
|
||||
IOMMUTLBEntry *entry)
|
||||
{
|
||||
IOMMUNotifier *iommu_notifier;
|
||||
IOMMUNotifierFlag request_flags;
|
||||
|
||||
assert(memory_region_is_iommu(mr));
|
||||
/*
|
||||
* Skip the notification if the notification does not overlap
|
||||
* with registered range.
|
||||
*/
|
||||
if (notifier->start > entry->iova + entry->addr_mask + 1 ||
|
||||
notifier->end < entry->iova) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (entry.perm & IOMMU_RW) {
|
||||
if (entry->perm & IOMMU_RW) {
|
||||
request_flags = IOMMU_NOTIFIER_MAP;
|
||||
} else {
|
||||
request_flags = IOMMU_NOTIFIER_UNMAP;
|
||||
}
|
||||
|
||||
if (notifier->notifier_flags & request_flags) {
|
||||
notifier->notify(notifier, entry);
|
||||
}
|
||||
}
|
||||
|
||||
void memory_region_notify_iommu(MemoryRegion *mr,
|
||||
IOMMUTLBEntry entry)
|
||||
{
|
||||
IOMMUNotifier *iommu_notifier;
|
||||
|
||||
assert(memory_region_is_iommu(mr));
|
||||
|
||||
IOMMU_NOTIFIER_FOREACH(iommu_notifier, mr) {
|
||||
/*
|
||||
* Skip the notification if the notification does not overlap
|
||||
* with registered range.
|
||||
*/
|
||||
if (iommu_notifier->start > entry.iova + entry.addr_mask + 1 ||
|
||||
iommu_notifier->end < entry.iova) {
|
||||
continue;
|
||||
}
|
||||
if (iommu_notifier->notifier_flags & request_flags) {
|
||||
iommu_notifier->notify(iommu_notifier, &entry);
|
||||
}
|
||||
memory_region_notify_one(iommu_notifier, &entry);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue