[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] VT-d: Fix free VT-d page table issue
# HG changeset patch # User Keir Fraser <keir.fraser@xxxxxxxxxx> # Date 1210148380 -3600 # Node ID fb58da5167497ce8752f99673149911909f0f269 # Parent 9d2a45d4b6c6ecf6d99f01dd035326d2215c548c VT-d: Fix free VT-d page table issue This patch frees VT-d page tables from pgd, rather than free them according to a guest address range. This fixes [Bug 1244] Poweroff/Destroying HVM guest causes HV crash. http://bugzilla.xensource.com/bugzilla/show_bug.cgi?id=1244. Signed-off-by: Weidong Han <weidong.han@xxxxxxxxx> --- xen/drivers/passthrough/vtd/iommu.c | 62 +++++++++++++++++++++++++++++++----- xen/drivers/passthrough/vtd/iommu.h | 1 2 files changed, 55 insertions(+), 8 deletions(-) diff -r 9d2a45d4b6c6 -r fb58da516749 xen/drivers/passthrough/vtd/iommu.c --- a/xen/drivers/passthrough/vtd/iommu.c Wed May 07 09:17:52 2008 +0100 +++ b/xen/drivers/passthrough/vtd/iommu.c Wed May 07 09:19:40 2008 +0100 @@ -678,17 +678,63 @@ void dma_pte_free_pagetable(struct domai } } - /* free all VT-d page tables when shut down or destroy domain. */ +static void iommu_free_next_pagetable(u64 pt_maddr, unsigned long index, + int level) +{ + struct acpi_drhd_unit *drhd; + unsigned long next_index; + struct dma_pte *pt_vaddr, *pde; + int next_level; + + if ( pt_maddr == 0 ) + return; + + pt_vaddr = (struct dma_pte *)map_vtd_domain_page(pt_maddr); + pde = &pt_vaddr[index]; + if ( dma_pte_addr(*pde) != 0 ) + { + next_level = level - 1; + if ( next_level > 1 ) + { + next_index = 0; + do + { + iommu_free_next_pagetable(pde->val, + next_index, next_level); + next_index++; + } while ( next_index < PTE_NUM ); + } + + dma_clear_pte(*pde); + drhd = list_entry(acpi_drhd_units.next, typeof(*drhd), list); + iommu_flush_cache_entry(drhd->iommu, pde); + free_pgtable_maddr(pde->val); + unmap_vtd_domain_page(pt_vaddr); + } + else + unmap_vtd_domain_page(pt_vaddr); +} + +/* free all VT-d page tables when shut down or destroy domain. */ static void iommu_free_pagetable(struct domain *domain) { + unsigned long index; struct hvm_iommu *hd = domain_hvm_iommu(domain); - int addr_width = agaw_to_width(hd->agaw); - u64 start, end; - - start = 0; - end = (((u64)1) << addr_width) - 1; - - dma_pte_free_pagetable(domain, start, end); + int total_level = agaw_to_level(hd->agaw); + + if ( hd->pgd_maddr != 0 ) + { + index = 0; + do + { + iommu_free_next_pagetable(hd->pgd_maddr, + index, total_level + 1); + index++; + } while ( index < PTE_NUM ); + + free_pgtable_maddr(hd->pgd_maddr); + hd->pgd_maddr = 0; + } } static int iommu_set_root_entry(struct iommu *iommu) diff -r 9d2a45d4b6c6 -r fb58da516749 xen/drivers/passthrough/vtd/iommu.h --- a/xen/drivers/passthrough/vtd/iommu.h Wed May 07 09:17:52 2008 +0100 +++ b/xen/drivers/passthrough/vtd/iommu.h Wed May 07 09:19:40 2008 +0100 @@ -235,6 +235,7 @@ struct context_entry { /* page table handling */ #define LEVEL_STRIDE (9) #define LEVEL_MASK ((1 << LEVEL_STRIDE) - 1) +#define PTE_NUM (1 << LEVEL_STRIDE) #define agaw_to_level(val) ((val) + 2) #define agaw_to_width(val) (30 + val * LEVEL_STRIDE) #define width_to_agaw(w) ((w - 30)/LEVEL_STRIDE) _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |