aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKeir Fraser <keir.fraser@citrix.com>2008-01-09 10:35:52 +0000
committerKeir Fraser <keir.fraser@citrix.com>2008-01-09 10:35:52 +0000
commit450bd7f584bc03c6f01555339aafe68ebaf8f115 (patch)
treea66b1c66f28444ec7e0b8c6cf3abf0197982ca0f
parentab6c6dfd00279d295ff6ef7fab902802244ba5d5 (diff)
downloadxen-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.c8
-rw-r--r--xen/arch/x86/hvm/vmx/vtd/intel-iommu.c2
-rw-r--r--xen/arch/x86/hvm/vmx/vtd/utils.c105
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 );
+ }
}