static int vtd_replay_hook(IOMMUTLBEntry *entry, void *private)
{
memory_region_notify_one((IOMMUNotifier *)private, entry);
@@ -2711,13 +2768,16 @@ static void vtd_iommu_replay(MemoryRegion *mr,
IOMMUNotifier *n)
if (vtd_dev_to_context_entry(s, bus_n, vtd_as->devfn, &ce) == 0) {
/*
- * Scanned a valid context entry, walk over the pages and
- * notify when needed.
+ * Scanned a valid context entry, we first make sure to remove
+ * all existing mappings in old domain, by sending UNMAP to
+ * all the notifiers. Then, we walk over the pages and notify
+ * with existing mapped new entries in the new domain.
*/
trace_vtd_replay_ce_valid(bus_n, PCI_SLOT(vtd_as->devfn),
PCI_FUNC(vtd_as->devfn),
VTD_CONTEXT_ENTRY_DID(ce.hi),
ce.hi, ce.lo);
+ vtd_address_space_unmap(vtd_as, n);
vtd_page_walk(&ce, 0, ~0, vtd_replay_hook, (void *)n, false);
} else {
trace_vtd_replay_ce_invalid(bus_n, PCI_SLOT(vtd_as->devfn),
diff --git a/hw/i386/intel_iommu_internal.h b/hw/i386/intel_iommu_intern