diff -r 81606e1d202e xen/arch/x86/mm/p2m.c --- a/xen/arch/x86/mm/p2m.c Wed Dec 01 16:13:30 2010 +0100 +++ b/xen/arch/x86/mm/p2m.c Wed Dec 01 17:11:16 2010 +0100 @@ -1381,7 +1381,16 @@ p2m_set_entry(struct p2m_domain *p2m, un && (gfn + (1UL << page_order) - 1 > p2m->max_mapped_pfn) ) p2m->max_mapped_pfn = gfn + (1UL << page_order) - 1; - if ( iommu_enabled && need_iommu(p2m->domain) ) + if ( iommu_enabled && iommu_super_page ) + { + if ( p2mt == p2m_ram_rw ) + iommu_map_pages(p2m->domain, gfn, mfn_x(mfn), + page_order, IOMMUF_readable|IOMMUF_writable); + else + iommu_unmap_pages(p2m->domain, gfn, page_order); + } + + else if ( iommu_enabled && need_iommu(p2m->domain) ) { if ( p2mt == p2m_ram_rw ) for ( i = 0; i < (1UL << page_order); i++ ) diff -r 81606e1d202e xen/drivers/passthrough/iommu.c --- a/xen/drivers/passthrough/iommu.c Wed Dec 01 16:13:30 2010 +0100 +++ b/xen/drivers/passthrough/iommu.c Wed Dec 01 17:11:16 2010 +0100 @@ -111,6 +111,9 @@ void __init iommu_dom0_init(struct domai if ( !iommu_enabled ) return; + if ( hd->platform_ops->map_pages == NULL ) + iommu_super_page = 0; + d->need_iommu = !!iommu_dom0_strict; if ( need_iommu(d) ) { @@ -177,7 +180,11 @@ int assign_device(struct domain *d, u8 b if ( has_arch_pdevs(d) && !need_iommu(d) ) { d->need_iommu = 1; - rc = iommu_populate_page_table(d); + /* Populate iommu page table when hardware does not + support super IO page */ + if ( (hd->platform_ops->map_pages == NULL) || + (!iommu_super_page) ) + rc = iommu_populate_page_table(d); goto done; } done: @@ -420,6 +427,33 @@ void iommu_suspend() ops->suspend(); } +int iommu_map_pages(struct domain *d, unsigned long gfn, + unsigned long mfn, unsigned int order, unsigned int flags) +{ + struct hvm_iommu *hd = domain_hvm_iommu(d); + + if ( !iommu_enabled || !hd->platform_ops ) + return 0; + + if ( hd->platform_ops->map_pages != NULL ) + return hd->platform_ops->map_pages(d, gfn, mfn, order, flags); + + return 0; +} + +int iommu_unmap_pages(struct domain *d, unsigned long gfn, unsigned int order) +{ + struct hvm_iommu *hd = domain_hvm_iommu(d); + + if ( !iommu_enabled || !hd->platform_ops ) + return 0; + + if ( hd->platform_ops->map_pages != NULL ) + return hd->platform_ops->unmap_pages(d, gfn, order); + + return 0; +} + /* * Local variables: * mode: C