[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] vt-d: Fix print_vtd_entries walk VTd mapping table.
# HG changeset patch # User Keir Fraser <keir.fraser@xxxxxxxxxx> # Date 1199874952 0 # Node ID f983aa8e4b26cbc97b738bc61a68ce6413a47897 # Parent 1b2be7cf0b7b4b639b7d6f027545930021ebe1e0 vt-d: Fix print_vtd_entries walk VTd mapping table. DMA request to above guest physical memory will cause VTd fault, in which print_vtd_entries() tries to walk VTd mapping table. However, during walking, current Xen code didn't check if the PTE is valid and may access to invalid memory address. Signed-off-by: Xiaowei Yang <xiaowei.yang@xxxxxxxxx> --- xen/arch/x86/hvm/vmx/vtd/dmar.c | 8 +- xen/arch/x86/hvm/vmx/vtd/intel-iommu.c | 2 xen/arch/x86/hvm/vmx/vtd/utils.c | 123 ++++++++++++--------------------- 3 files changed, 52 insertions(+), 81 deletions(-) diff -r 1b2be7cf0b7b -r f983aa8e4b26 xen/arch/x86/hvm/vmx/vtd/dmar.c --- a/xen/arch/x86/hvm/vmx/vtd/dmar.c Wed Jan 09 10:32:13 2008 +0000 +++ b/xen/arch/x86/hvm/vmx/vtd/dmar.c Wed Jan 09 10:35:52 2008 +0000 @@ -103,7 +103,11 @@ struct acpi_drhd_unit * acpi_find_matche list_for_each_entry ( drhd, &acpi_drhd_units, list ) { if ( drhd->include_all ) + { include_all_drhd = drhd; + continue; + } + if ( acpi_pci_device_match(drhd->devices, drhd->devices_cnt, dev) ) { @@ -119,7 +123,7 @@ struct acpi_drhd_unit * acpi_find_matche gdprintk(XENLOG_INFO VTDPREFIX, "acpi_find_matched_drhd_unit:include_all_drhd->addr = %lx\n", include_all_drhd->address); - return include_all_drhd;; + return include_all_drhd; } return NULL; @@ -513,7 +517,7 @@ static int __init acpi_parse_dmar(unsign ret = acpi_parse_one_rmrr(entry_header); break; case ACPI_DMAR_ATSR: - printk(KERN_INFO PREFIX "found ACPI_DMAR_RMRR\n"); + printk(KERN_INFO PREFIX "found ACPI_DMAR_ATSR\n"); ret = acpi_parse_one_atsr(entry_header); break; default: diff -r 1b2be7cf0b7b -r f983aa8e4b26 xen/arch/x86/hvm/vmx/vtd/intel-iommu.c --- a/xen/arch/x86/hvm/vmx/vtd/intel-iommu.c Wed Jan 09 10:32:13 2008 +0000 +++ b/xen/arch/x86/hvm/vmx/vtd/intel-iommu.c Wed Jan 09 10:35:52 2008 +0000 @@ -528,7 +528,6 @@ void iommu_flush_all(void) { struct acpi_drhd_unit *drhd; struct iommu *iommu; - int i = 0; wbinvd(); for_each_drhd_unit ( drhd ) @@ -536,7 +535,6 @@ void iommu_flush_all(void) iommu = drhd->iommu; iommu_flush_context_global(iommu, 0); iommu_flush_iotlb_global(iommu, 0); - i++; } } diff -r 1b2be7cf0b7b -r f983aa8e4b26 xen/arch/x86/hvm/vmx/vtd/utils.c --- a/xen/arch/x86/hvm/vmx/vtd/utils.c Wed Jan 09 10:32:13 2008 +0000 +++ b/xen/arch/x86/hvm/vmx/vtd/utils.c Wed Jan 09 10:35:52 2008 +0000 @@ -154,8 +154,9 @@ void print_vtd_entries(struct domain *d, struct iommu *iommu; struct context_entry *ctxt_entry; struct root_entry *root_entry; - u64 *l4 = NULL, *l3, *l2, *l1; - u32 l4_index = 0, l3_index, l2_index, l1_index; + struct dma_pte pte; + u64 *l; + u32 l_index; u32 i = 0; int level = agaw_to_level(hd->agaw); @@ -176,20 +177,17 @@ void print_vtd_entries(struct domain *d, iommu = drhd->iommu; root_entry = iommu->root_entry; + if ( root_entry == NULL ) + { + printk(" root_entry == NULL\n"); + continue; + } + printk(" root_entry = %p\n", root_entry); - if ( root_entry == NULL ) - { - printk(" root_entry == NULL\n"); - continue; - } - printk(" root_entry[%x] = %"PRIx64"\n", bus, root_entry[bus].val); - printk(" maddr_to_virt(root_entry[%x]) = %p\n", - bus, maddr_to_virt(root_entry[bus].val)); - - if ( root_entry[bus].val == 0 ) - { - printk(" root_entry[%x].lo == 0\n", bus); + if ( !root_present(root_entry[bus]) ) + { + printk(" root_entry[%x] not present\n", bus); continue; } @@ -201,73 +199,44 @@ void print_vtd_entries(struct domain *d, continue; } - if ( ctxt_entry[devfn].lo == 0 ) - { - printk(" ctxt_entry[%x].lo == 0\n", devfn); - continue; - } - printk(" context = %p\n", ctxt_entry); printk(" context[%x] = %"PRIx64" %"PRIx64"\n", devfn, ctxt_entry[devfn].hi, ctxt_entry[devfn].lo); - printk(" maddr_to_virt(context[%x].lo) = %p\n", - devfn, maddr_to_virt(ctxt_entry[devfn].lo)); - printk(" context[%x] = %"PRIx64"\n", devfn, ctxt_entry[devfn].lo); - - switch ( level ) - { - case VTD_PAGE_TABLE_LEVEL_3: - l3 = maddr_to_virt(ctxt_entry[devfn].lo); - l3 = (u64*)(((unsigned long)l3 >> PAGE_SHIFT_4K) << PAGE_SHIFT_4K); - printk(" l3 = %p\n", l3); - if ( l3 == NULL ) - continue; - l3_index = get_level_index(gmfn, 3); - printk(" l3_index = %x\n", l3_index); - printk(" l3[%x] = %"PRIx64"\n", l3_index, l3[l3_index]); - - break; - case VTD_PAGE_TABLE_LEVEL_4: - l4 = maddr_to_virt(ctxt_entry[devfn].lo); - l4 = (u64*)(((unsigned long)l4 >> PAGE_SHIFT_4K) << PAGE_SHIFT_4K); - printk(" l4 = %p\n", l4); - if ( l4 == NULL ) - continue; - l4_index = get_level_index(gmfn, 4); - printk(" l4_index = %x\n", l4_index); - printk(" l4[%x] = %"PRIx64"\n", l4_index, l4[l4_index]); - - l3 = maddr_to_virt(l4[l4_index]); - l3 = (u64*)(((unsigned long)l3 >> PAGE_SHIFT_4K) << PAGE_SHIFT_4K); - printk(" l3 = %p\n", l3); - if ( l3 == NULL ) - continue; - l3_index = get_level_index(gmfn, 3); - printk(" l3_index = %x\n", l3_index); - printk(" l3[%x] = %"PRIx64"\n", l3_index, l3[l3_index]); - - break; - default: + if ( !context_present(ctxt_entry[devfn]) ) + { + printk(" ctxt_entry[%x] not present\n", devfn); + continue; + } + + if ( level != VTD_PAGE_TABLE_LEVEL_3 && + level != VTD_PAGE_TABLE_LEVEL_4) + { printk("Unsupported VTD page table level (%d)!\n", level); continue; } - l2 = maddr_to_virt(l3[l3_index]); - l2 = (u64*)(((unsigned long)l2 >> PAGE_SHIFT_4K) << PAGE_SHIFT_4K); - printk(" l2 = %p\n", l2); - if ( l2 == NULL ) - continue; - l2_index = get_level_index(gmfn, 2); - printk(" l2_index = %x\n", l2_index); - printk(" l2[%x] = %"PRIx64"\n", l2_index, l2[l2_index]); - - l1 = maddr_to_virt(l2[l2_index]); - l1 = (u64*)(((unsigned long)l1 >> PAGE_SHIFT_4K) << PAGE_SHIFT_4K); - printk(" l1 = %p\n", l1); - if ( l1 == NULL ) - continue; - l1_index = get_level_index(gmfn, 1); - printk(" l1_index = %x\n", l1_index); - printk(" l1[%x] = %"PRIx64"\n", l1_index, l1[l1_index]); - } -} + l = maddr_to_virt(ctxt_entry[devfn].lo); + do + { + l = (u64*)(((unsigned long)l >> PAGE_SHIFT_4K) << PAGE_SHIFT_4K); + printk(" l%d = %p\n", level, l); + if ( l == NULL ) + { + printk(" l%d == NULL\n", level); + break; + } + l_index = get_level_index(gmfn, level); + printk(" l%d_index = %x\n", level, l_index); + printk(" l%d[%x] = %"PRIx64"\n", level, l_index, l[l_index]); + + pte.val = l[l_index]; + if ( !dma_pte_present(pte) ) + { + printk(" l%d[%x] not present\n", level, l_index); + break; + } + + l = maddr_to_virt(l[l_index]); + } while ( --level ); + } +} _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |