diff options
author | Keir Fraser <keir.fraser@citrix.com> | 2008-01-09 10:35:52 +0000 |
---|---|---|
committer | Keir Fraser <keir.fraser@citrix.com> | 2008-01-09 10:35:52 +0000 |
commit | 450bd7f584bc03c6f01555339aafe68ebaf8f115 (patch) | |
tree | a66b1c66f28444ec7e0b8c6cf3abf0197982ca0f | |
parent | ab6c6dfd00279d295ff6ef7fab902802244ba5d5 (diff) | |
download | xen-450bd7f584bc03c6f01555339aafe68ebaf8f115.tar.gz xen-450bd7f584bc03c6f01555339aafe68ebaf8f115.tar.bz2 xen-450bd7f584bc03c6f01555339aafe68ebaf8f115.zip |
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@intel.com>
-rw-r--r-- | xen/arch/x86/hvm/vmx/vtd/dmar.c | 8 | ||||
-rw-r--r-- | xen/arch/x86/hvm/vmx/vtd/intel-iommu.c | 2 | ||||
-rw-r--r-- | xen/arch/x86/hvm/vmx/vtd/utils.c | 105 |
3 files changed, 43 insertions, 72 deletions
diff --git a/xen/arch/x86/hvm/vmx/vtd/dmar.c b/xen/arch/x86/hvm/vmx/vtd/dmar.c index 786186966f..62e32e3610 100644 --- a/xen/arch/x86/hvm/vmx/vtd/dmar.c +++ b/xen/arch/x86/hvm/vmx/vtd/dmar.c @@ -103,7 +103,11 @@ struct acpi_drhd_unit * acpi_find_matched_drhd_unit(struct pci_dev *dev) 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_matched_drhd_unit(struct pci_dev *dev) 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(unsigned long phys_addr, 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 --git a/xen/arch/x86/hvm/vmx/vtd/intel-iommu.c b/xen/arch/x86/hvm/vmx/vtd/intel-iommu.c index 29f8f195de..fb8fdb77a1 100644 --- a/xen/arch/x86/hvm/vmx/vtd/intel-iommu.c +++ b/xen/arch/x86/hvm/vmx/vtd/intel-iommu.c @@ -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 --git a/xen/arch/x86/hvm/vmx/vtd/utils.c b/xen/arch/x86/hvm/vmx/vtd/utils.c index 55a7149a7e..82f8366ae4 100644 --- a/xen/arch/x86/hvm/vmx/vtd/utils.c +++ b/xen/arch/x86/hvm/vmx/vtd/utils.c @@ -154,8 +154,9 @@ void print_vtd_entries(struct domain *d, int bus, int devfn, 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, int bus, int devfn, iommu = drhd->iommu; root_entry = iommu->root_entry; - printk(" root_entry = %p\n", root_entry); if ( root_entry == NULL ) { printk(" root_entry == NULL\n"); continue; } + printk(" root_entry = %p\n", root_entry); 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 ) + if ( !root_present(root_entry[bus]) ) { - printk(" root_entry[%x].lo == 0\n", bus); + printk(" root_entry[%x] not present\n", bus); continue; } @@ -201,73 +199,44 @@ void print_vtd_entries(struct domain *d, int bus, int devfn, 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 ) + if ( !context_present(ctxt_entry[devfn]) ) { - 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: - printk("Unsupported VTD page table level (%d)!\n", level); + printk(" ctxt_entry[%x] not present\n", devfn); 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 ) + if ( level != VTD_PAGE_TABLE_LEVEL_3 && + level != VTD_PAGE_TABLE_LEVEL_4) + { + printk("Unsupported VTD page table level (%d)!\n", level); 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 ); + } } |