Add the minimal data structures required to maintain a list of address spaces (i.e. devices) with registered notifiers, and to update the type of events that require notifications. Note that the ability to register for MAP notifications is not available. It will be unblocked by following changes that enable the synchronization of guest I/O page tables with host IOMMU state, at which point an amd-iommu device property will be introduced to control this capability.
Signed-off-by: Alejandro Jimenez <alejandro.j.jime...@oracle.com> --- hw/i386/amd_iommu.c | 20 ++++++++++++++++++++ hw/i386/amd_iommu.h | 3 +++ 2 files changed, 23 insertions(+) diff --git a/hw/i386/amd_iommu.c b/hw/i386/amd_iommu.c index 0e45435c77be9..d8a451b3a5ff1 100644 --- a/hw/i386/amd_iommu.c +++ b/hw/i386/amd_iommu.c @@ -66,6 +66,11 @@ struct AMDVIAddressSpace { MemoryRegion iommu_nodma; /* Alias of shared nodma memory region */ MemoryRegion iommu_ir; /* Device's interrupt remapping region */ AddressSpace as; /* device's corresponding address space */ + + /* DMA address translation support */ + IOMMUNotifierFlag notifier_flags; + /* entry in list of Address spaces with registered notifiers */ + QLIST_ENTRY(AMDVIAddressSpace) next; }; /* AMDVI cache entry */ @@ -1773,6 +1778,7 @@ static AddressSpace *amdvi_host_dma_iommu(PCIBus *bus, void *opaque, int devfn) iommu_as[devfn]->bus_num = (uint8_t)bus_num; iommu_as[devfn]->devfn = (uint8_t)devfn; iommu_as[devfn]->iommu_state = s; + iommu_as[devfn]->notifier_flags = IOMMU_NOTIFIER_NONE; amdvi_dev_as = iommu_as[devfn]; @@ -1846,6 +1852,7 @@ static int amdvi_iommu_notify_flag_changed(IOMMUMemoryRegion *iommu, Error **errp) { AMDVIAddressSpace *as = container_of(iommu, AMDVIAddressSpace, iommu); + AMDVIState *s = as->iommu_state; if (new & IOMMU_NOTIFIER_MAP) { error_setg(errp, @@ -1854,6 +1861,19 @@ static int amdvi_iommu_notify_flag_changed(IOMMUMemoryRegion *iommu, PCI_FUNC(as->devfn)); return -EINVAL; } + + /* + * Update notifier flags for address space and the list of address spaces + * with registered notifiers. + */ + as->notifier_flags = new; + + if (old == IOMMU_NOTIFIER_NONE) { + QLIST_INSERT_HEAD(&s->amdvi_as_with_notifiers, as, next); + } else if (new == IOMMU_NOTIFIER_NONE) { + QLIST_REMOVE(as, next); + } + return 0; } diff --git a/hw/i386/amd_iommu.h b/hw/i386/amd_iommu.h index 9f833b297d25c..b51aa74368995 100644 --- a/hw/i386/amd_iommu.h +++ b/hw/i386/amd_iommu.h @@ -409,6 +409,9 @@ struct AMDVIState { /* for each served device */ AMDVIAddressSpace **address_spaces[PCI_BUS_MAX]; + /* list of address spaces with registered notifiers */ + QLIST_HEAD(, AMDVIAddressSpace) amdvi_as_with_notifiers; + /* IOTLB */ GHashTable *iotlb; -- 2.43.5