[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


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.