diff --git a/xen/arch/x86/mm/p2m-ept.c b/xen/arch/x86/mm/p2m-ept.c index fb2dfdb985..02071752e8 100644 --- a/xen/arch/x86/mm/p2m-ept.c +++ b/xen/arch/x86/mm/p2m-ept.c @@ -90,6 +90,19 @@ static int atomic_write_ept_entry(ept_entry_t *entryptr, ept_entry_t new, write_atomic(&entryptr->epte, new.epte); + /* + * The recalc field on the EPT is used to signal either that a + * recalculation of the EMT field is required (which doesn't effect the + * IOMMU), or a type change. Type changes can only be between ram_rw, + * logdirty and ioreq_server: changes to/from logdirty won't work well with + * an IOMMU anyway, as IOMMU #PFs are not synchronous and will lead to + * aborts, and changes to/from ioreq_server are already fully flushed + * before returning to guest context (see + * XEN_DMOP_map_mem_type_to_ioreq_server). + */ + if ( !new.recalc && iommu_hap_pt_share ) + iommu_sync_cache(entryptr, sizeof(*entryptr)); + if ( unlikely(oldmfn != mfn_x(INVALID_MFN)) ) put_page(mfn_to_page(_mfn(oldmfn))); @@ -319,6 +332,9 @@ static bool_t ept_split_super_page(struct p2m_domain *p2m, break; } + if ( iommu_hap_pt_share ) + iommu_sync_cache(table, EPT_PAGETABLE_ENTRIES * sizeof(ept_entry_t)); + unmap_domain_page(table); /* Even failed we should install the newly allocated ept page. */ @@ -378,6 +394,9 @@ static int ept_next_level(struct p2m_domain *p2m, bool_t read_only, if ( !next ) return GUEST_TABLE_MAP_FAILED; + if ( iommu_hap_pt_share ) + iommu_sync_cache(next, EPT_PAGETABLE_ENTRIES * sizeof(ept_entry_t)); + rc = atomic_write_ept_entry(ept_entry, e, next_level); ASSERT(rc == 0); } @@ -875,7 +894,7 @@ out: need_modify_vtd_table ) { if ( iommu_hap_pt_share ) - rc = iommu_pte_flush(d, gfn, &ept_entry->epte, order, vtd_pte_present); + rc = iommu_flush_iotlb(d, gfn, vtd_pte_present, 1u << order); else { if ( iommu_flags ) diff --git a/xen/drivers/passthrough/vtd/iommu.c b/xen/drivers/passthrough/vtd/iommu.c index 05fe61f69e..f499c6f430 100644 --- a/xen/drivers/passthrough/vtd/iommu.c +++ b/xen/drivers/passthrough/vtd/iommu.c @@ -612,10 +612,8 @@ static int __must_check iommu_flush_all(void) return rc; } -static int __must_check iommu_flush_iotlb(struct domain *d, - unsigned long gfn, - bool_t dma_old_pte_present, - unsigned int page_count) +int iommu_flush_iotlb(struct domain *d, unsigned long gfn, + bool dma_old_pte_present, unsigned int page_count) { struct domain_iommu *hd = dom_iommu(d); struct acpi_drhd_unit *drhd; @@ -1880,53 +1878,6 @@ static int __must_check intel_iommu_unmap_page(struct domain *d, return dma_pte_clear_one(d, (paddr_t)gfn << PAGE_SHIFT_4K); } -int iommu_pte_flush(struct domain *d, u64 gfn, u64 *pte, - int order, int present) -{ - struct acpi_drhd_unit *drhd; - struct iommu *iommu = NULL; - struct domain_iommu *hd = dom_iommu(d); - bool_t flush_dev_iotlb; - int iommu_domid; - int rc = 0; - - iommu_sync_cache(pte, sizeof(struct dma_pte)); - - for_each_drhd_unit ( drhd ) - { - iommu = drhd->iommu; - if ( !test_bit(iommu->index, &hd->arch.iommu_bitmap) ) - continue; - - flush_dev_iotlb = !!find_ats_dev_drhd(iommu); - iommu_domid= domain_iommu_domid(d, iommu); - if ( iommu_domid == -1 ) - continue; - - rc = iommu_flush_iotlb_psi(iommu, iommu_domid, - (paddr_t)gfn << PAGE_SHIFT_4K, - order, !present, flush_dev_iotlb); - if ( rc > 0 ) - { - iommu_flush_write_buffer(iommu); - rc = 0; - } - } - - if ( unlikely(rc) ) - { - if ( !d->is_shutting_down && printk_ratelimit() ) - printk(XENLOG_ERR VTDPREFIX - " d%d: IOMMU pages flush failed: %d\n", - d->domain_id, rc); - - if ( !is_hardware_domain(d) ) - domain_crash(d); - } - - return rc; -} - static int __init vtd_ept_page_compatible(struct iommu *iommu) { u64 ept_cap, vtd_cap = iommu->cap; diff --git a/xen/include/asm-x86/iommu.h b/xen/include/asm-x86/iommu.h index 16ff2e94c2..dfc9b77594 100644 --- a/xen/include/asm-x86/iommu.h +++ b/xen/include/asm-x86/iommu.h @@ -87,8 +87,9 @@ int iommu_setup_hpet_msi(struct msi_desc *); /* While VT-d specific, this must get declared in a generic header. */ int adjust_vtd_irq_affinities(void); -int __must_check iommu_pte_flush(struct domain *d, u64 gfn, u64 *pte, - int order, int present); +int __must_check iommu_flush_iotlb(struct domain *d, unsigned long gfn, + bool dma_old_pte_present, + unsigned int page_count); bool_t iommu_supports_eim(void); int iommu_enable_x2apic_IR(void); void iommu_disable_x2apic_IR(void);