@@ -3850,7 +3850,7 @@ static void vtd_iommu_replay(IOMMUMemoryRegion *iommu_mr, IOMMUNotifier *n)
.domain_id = vtd_get_domain_id(s, &ce, vtd_as->pasid),
};
- vtd_page_walk(s, &ce, 0, ~0ULL, &info, vtd_as->pasid);
+ vtd_page_walk(s, &ce, n->start, n->end, &info, vtd_as->pasid);
}
} else {
trace_vtd_replay_ce_invalid(bus_n, PCI_SLOT(vtd_as->devfn),
@@ -425,12 +425,14 @@ struct IOMMUMemoryRegionClass {
* Called to handle memory_region_iommu_replay().
*
* The default implementation of memory_region_iommu_replay() is to
- * call the IOMMU translate method for every page in the address space
- * with flag == IOMMU_NONE and then call the notifier if translate
- * returns a valid mapping. If this method is implemented then it
- * overrides the default behaviour, and must provide the full semantics
- * of memory_region_iommu_replay(), by calling @notifier for every
- * translation present in the IOMMU.
+ * call the IOMMU translate method for every page falling in the
+ * intersection of the IOMMU MemoryRegion and the MemoryRegion which
+ * the notifier was registered for with flag == IOMMU_NONE and then
+ * call the notifier if translate returns a valid mapping. If this
+ * method is implemented then it overrides the default behavior,
+ * and must provide the full semantics of memory_region_iommu_replay(),
+ * by calling @notifier for every translation present in the IOMMU
+ * that is within the MemoryRegion the notifier was registered for.
*
* Optional method -- an IOMMU only needs to provide this method
* if the default is inefficient or produces undesirable side effects.
@@ -1760,9 +1762,10 @@ int memory_region_register_iommu_notifier(MemoryRegion *mr,
IOMMUNotifier *n, Error **errp);
/**
- * memory_region_iommu_replay: replay existing IOMMU translations to
+ * memory_region_iommu_replay: replay existing IOMMU translations in
+ * intersection part of IOMMU memory region and notifier's scope to
* a notifier with the minimum page granularity returned by
- * mr->iommu_ops->get_page_size().
+ * memory_region_iommu_get_min_page_size().
*
* Note: this is not related to record-and-replay functionality.
*
@@ -1775,8 +1778,7 @@ void memory_region_iommu_replay(IOMMUMemoryRegion *iommu_mr, IOMMUNotifier *n);
* 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
+ * @mr: the memory region which was observed.
* @n: the notifier to be removed.
*/
void memory_region_unregister_iommu_notifier(MemoryRegion *mr,
@@ -1925,7 +1925,7 @@ void memory_region_iommu_replay(IOMMUMemoryRegion *iommu_mr, IOMMUNotifier *n)
{
MemoryRegion *mr = MEMORY_REGION(iommu_mr);
IOMMUMemoryRegionClass *imrc = IOMMU_MEMORY_REGION_GET_CLASS(iommu_mr);
- hwaddr addr, granularity;
+ hwaddr addr, end, granularity;
IOMMUTLBEntry iotlb;
/* If the IOMMU has its own replay callback, override */
@@ -1935,8 +1935,9 @@ void memory_region_iommu_replay(IOMMUMemoryRegion *iommu_mr, IOMMUNotifier *n)
}
granularity = memory_region_iommu_get_min_page_size(iommu_mr);
+ end = MIN(n->end, memory_region_size(mr));
- for (addr = 0; addr < memory_region_size(mr); addr += granularity) {
+ for (addr = n->start; addr < end; addr += granularity) {
iotlb = imrc->translate(iommu_mr, addr, IOMMU_NONE, n->iommu_idx);
if (iotlb.perm != IOMMU_NONE) {
n->notify(n, &iotlb);