diff -r a4136cb2e23f tools/python/xen/xend/XendDomainInfo.py --- a/tools/python/xen/xend/XendDomainInfo.py Tue Apr 22 13:39:29 2008 +0800 +++ b/tools/python/xen/xend/XendDomainInfo.py Tue Apr 22 14:14:04 2008 +0800 @@ -2132,8 +2132,13 @@ class XendDomainInfo: # set memory limit xc.domain_setmaxmem(self.domid, maxmem) + # Reserve 1 page per MiB of RAM for separate VT-d page table. + vtd_mem = 4 * (self.info['memory_static_max'] / 1024 / 1024) + # Round vtd_mem up to a multiple of a MiB. + vtd_mem = ((vtd_mem + 1023) / 1024) * 1024 + # Make sure there's enough RAM available for the domain - balloon.free(memory + shadow) + balloon.free(memory + shadow + vtd_mem) # Set up the shadow memory shadow_cur = xc.shadow_mem_control(self.domid, shadow / 1024) diff -r a4136cb2e23f xen/arch/x86/mm/p2m.c --- a/xen/arch/x86/mm/p2m.c Tue Apr 22 13:39:29 2008 +0800 +++ b/xen/arch/x86/mm/p2m.c Tue Apr 22 14:19:23 2008 +0800 @@ -259,12 +259,9 @@ p2m_set_entry(struct domain *d, unsigned if ( iommu_enabled && is_hvm_domain(d) ) { - if ( boot_cpu_data.x86_vendor == X86_VENDOR_INTEL ) - { - if ( (p2mt == p2m_mmio_direct) ) - iommu_flush(d, gfn, (u64*)p2m_entry); - } - else if ( boot_cpu_data.x86_vendor == X86_VENDOR_AMD ) + if ( vtd_share ) + iommu_flush(d, gfn, (u64*)p2m_entry); + else { if ( p2mt == p2m_ram_rw ) iommu_map_page(d, gfn, mfn_x(mfn)); @@ -530,7 +527,7 @@ int p2m_alloc_table(struct domain *d, } #if CONFIG_PAGING_LEVELS >= 3 - if (vtd_enabled && is_hvm_domain(d)) + if ( vtd_share && vtd_enabled && is_hvm_domain(d) ) iommu_set_pgd(d); #endif diff -r a4136cb2e23f xen/drivers/passthrough/vtd/dmar.c --- a/xen/drivers/passthrough/vtd/dmar.c Tue Apr 22 13:39:29 2008 +0800 +++ b/xen/drivers/passthrough/vtd/dmar.c Tue Apr 22 14:14:04 2008 +0800 @@ -32,6 +32,10 @@ int vtd_enabled = 1; +/* Specify whether VT-d page table shares with P2M table or not. */ +int vtd_share; +boolean_param("vtd_share", vtd_share); + #undef PREFIX #define PREFIX VTDPREFIX "ACPI DMAR:" #define DEBUG diff -r a4136cb2e23f xen/drivers/passthrough/vtd/iommu.c --- a/xen/drivers/passthrough/vtd/iommu.c Tue Apr 22 13:39:29 2008 +0800 +++ b/xen/drivers/passthrough/vtd/iommu.c Tue Apr 22 14:14:04 2008 +0800 @@ -676,6 +676,58 @@ void dma_pte_free_pagetable(struct domai { free_pgtable_maddr(hd->pgd_maddr); hd->pgd_maddr = 0; + } +} + +/* If VT-d page table doesn't share with p2m table, need to free + * VT-d page table explicitely when shut down or destroy domain. + */ +static void iommu_free_pagetable(struct domain *domain) +{ + struct hvm_iommu *hd = domain_hvm_iommu(domain); + int addr_width = agaw_to_width(hd->agaw); + int total_level = agaw_to_level(hd->agaw); + struct acpi_drhd_unit *drhd; + struct iommu *iommu; + int level; + struct dma_pte *page, *pte; + u64 pg_maddr, tmp; + u64 start, end; + + if ( !vtd_share ) + { + drhd = list_entry(acpi_drhd_units.next, typeof(*drhd), list); + iommu = drhd->iommu; + + start = 0; + end = (((u64)1) << addr_width) - 1; + + level = 2; + while ( level <= total_level ) + { + tmp = align_to_level(start, level); + if ( (tmp >= end) || ((tmp + level_size(level)) > end) ) + break; + + while ( tmp < end ) + { + pg_maddr = dma_addr_level_page_maddr(domain, tmp, level); + if ( pg_maddr == 0 ) + { + tmp += level_size(level); + continue; + } + page = (struct dma_pte *)map_vtd_domain_page(pg_maddr); + pte = page + address_level_offset(tmp, level); + dma_clear_pte(*pte); + iommu_flush_cache_entry(iommu, pte); + unmap_vtd_domain_page(page); + free_pgtable_maddr(pg_maddr); + + tmp += level_size(level); + } + level++; + } } } @@ -1529,9 +1581,10 @@ void iommu_domain_teardown(struct domain if ( list_empty(&acpi_drhd_units) ) return; - iommu_domid_release(d); + iommu_free_pagetable(d); iommu_free_pgd(d); return_devices_to_dom0(d); + iommu_domid_release(d); } static int domain_context_mapped(struct pci_dev *pdev) diff -r a4136cb2e23f xen/include/xen/iommu.h --- a/xen/include/xen/iommu.h Tue Apr 22 13:39:29 2008 +0800 +++ b/xen/include/xen/iommu.h Tue Apr 22 14:14:04 2008 +0800 @@ -26,6 +26,7 @@ #include #include +extern int vtd_share; extern int vtd_enabled; extern int iommu_enabled;