diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c index 77ae77f..4e23875 100644 --- a/xen/arch/x86/mm.c +++ b/xen/arch/x86/mm.c @@ -4699,7 +4699,7 @@ long arch_memory_op(int op, XEN_GUEST_HANDLE(void) arg) { case XENMEM_add_to_physmap: { - struct xen_add_to_physmap xatp; + struct xen_add_to_physmap xatp, start_xatp; struct domain *d; unsigned int size, i; @@ -4720,8 +4720,11 @@ long arch_memory_op(int op, XEN_GUEST_HANDLE(void) arg) if ( xatp.space == XENMAPSPACE_gmfn_range ) { size = xatp.size; + if ( need_iommu(d) ) + d->dont_flush_iotlb = 1; } + start_xatp = xatp; for ( i = 0; i < size; i++ ) { xenmem_add_to_physmap(d, xatp); @@ -4729,6 +4732,13 @@ long arch_memory_op(int op, XEN_GUEST_HANDLE(void) arg) xatp.gpfn++; } + if ( xatp.space == XENMAPSPACE_gmfn_range && need_iommu(d) ) + { + d->dont_flush_iotlb = 0; + iommu_iotlb_flush(d, start_xatp.idx, size); + iommu_iotlb_flush(d, start_xatp.gpfn, size); + } + rcu_unlock_domain(d); return rc; diff --git a/xen/drivers/passthrough/iommu.c b/xen/drivers/passthrough/iommu.c index 9c62861..7f87aed 100644 --- a/xen/drivers/passthrough/iommu.c +++ b/xen/drivers/passthrough/iommu.c @@ -113,10 +113,13 @@ void __init iommu_dom0_init(struct domain *d) return; d->need_iommu = !!iommu_dom0_strict; + d->dont_flush_iotlb = 0; if ( need_iommu(d) ) { struct page_info *page; unsigned int i = 0; + + d->dont_flush_iotlb = 1; page_list_for_each ( page, &d->page_list ) { unsigned long mfn = page_to_mfn(page); @@ -129,6 +132,8 @@ void __init iommu_dom0_init(struct domain *d) if ( !(i++ & 0xfffff) ) process_pending_softirqs(); } + d->dont_flush_iotlb = 0; + iommu_iotlb_flush_all(d); } return hd->platform_ops->dom0_init(d); @@ -210,6 +215,7 @@ static int assign_device(struct domain *d, u16 seg, u8 bus, u8 devfn) if ( has_arch_pdevs(d) && !need_iommu(d) ) { d->need_iommu = 1; + d->dont_flush_iotlb = 0; if ( !iommu_use_hap_pt(d) ) rc = iommu_populate_page_table(d); goto done; diff --git a/xen/drivers/passthrough/vtd/iommu.c b/xen/drivers/passthrough/vtd/iommu.c index 7ec9541..336232e 100644 --- a/xen/drivers/passthrough/vtd/iommu.c +++ b/xen/drivers/passthrough/vtd/iommu.c @@ -660,7 +660,8 @@ static void dma_pte_clear_one(struct domain *domain, u64 addr) spin_unlock(&hd->mapping_lock); iommu_flush_cache_entry(pte, sizeof(struct dma_pte)); - __intel_iommu_iotlb_flush(domain, addr >> PAGE_SHIFT_4K , 0, 1); + if ( !domain->dont_flush_iotlb ) + __intel_iommu_iotlb_flush(domain, addr >> PAGE_SHIFT_4K , 0, 1); unmap_vtd_domain_page(page); @@ -1753,7 +1754,8 @@ static int intel_iommu_map_page( spin_unlock(&hd->mapping_lock); unmap_vtd_domain_page(page); - __intel_iommu_iotlb_flush(d, gfn, dma_pte_present(old), 1); + if ( !d->dont_flush_iotlb ) + __intel_iommu_iotlb_flush(d, gfn, dma_pte_present(old), 1); return 0; } diff --git a/xen/include/xen/sched.h b/xen/include/xen/sched.h index 3ba5495..922f068 100644 --- a/xen/include/xen/sched.h +++ b/xen/include/xen/sched.h @@ -244,6 +244,7 @@ struct domain bool_t is_hvm; /* Does this guest need iommu mappings? */ bool_t need_iommu; + bool_t dont_flush_iotlb; /* Is this guest fully privileged (aka dom0)? */ bool_t is_privileged; /* Which guest this guest has privileges on */