if (try_unmap) {
bool unmap_all = false;
+ IOMMUTLBEntry entry = {}, *iotlb = NULL;
if (int128_eq(llsize, int128_2_64())) {
assert(!iova);
unmap_all = true;
llsize = int128_zero();
}
+
+ /*
+ * Fake an IOTLB entry for identity mapping which is needed by dirty
+ * tracking when switch out of PT domain. In fact, in unmap_bitmap,
+ * only translated_addr field is used to set dirty bitmap.
+ *
+ * Note: When switch into PT domain from DMA domain, the whole IOMMU
+ * MR is deleted without iotlb, before that happen, we depend on
+ * vIOMMU to send unmap notification with accurate iotlb entry to
+ * VFIO. See vtd_address_space_unmap_in_dirty_tracking() for example,
+ * it is triggered during switching to block domain because vtd does
+ * not support direct switching from DMA to PT domain.
+ */
+ if (global_dirty_tracking && memory_region_is_ram(section->mr)) {
+ entry.iova = iova;
+ entry.translated_addr = iova;
+ iotlb = &entry;
+ }
+
ret = vfio_container_dma_unmap(bcontainer, iova, int128_get64(llsize),
- NULL, unmap_all);
+ iotlb, unmap_all);
if (ret) {
error_report("vfio_container_dma_unmap(%p, 0x%"HWADDR_PRIx", "
"0x%"HWADDR_PRIx") = %d (%s)",