ia64/xen-unstable

changeset 16698:f983aa8e4b26

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>
author Keir Fraser <keir.fraser@citrix.com>
date Wed Jan 09 10:35:52 2008 +0000 (2008-01-09)
parents 1b2be7cf0b7b
children 7e400607cdd8
files xen/arch/x86/hvm/vmx/vtd/dmar.c xen/arch/x86/hvm/vmx/vtd/intel-iommu.c xen/arch/x86/hvm/vmx/vtd/utils.c
line diff
     1.1 --- a/xen/arch/x86/hvm/vmx/vtd/dmar.c	Wed Jan 09 10:32:13 2008 +0000
     1.2 +++ b/xen/arch/x86/hvm/vmx/vtd/dmar.c	Wed Jan 09 10:35:52 2008 +0000
     1.3 @@ -103,7 +103,11 @@ struct acpi_drhd_unit * acpi_find_matche
     1.4      list_for_each_entry ( drhd, &acpi_drhd_units, list )
     1.5      {
     1.6          if ( drhd->include_all )
     1.7 +        {
     1.8              include_all_drhd = drhd;
     1.9 +            continue;
    1.10 +        }
    1.11 +
    1.12          if ( acpi_pci_device_match(drhd->devices,
    1.13                                     drhd->devices_cnt, dev) )
    1.14          {
    1.15 @@ -119,7 +123,7 @@ struct acpi_drhd_unit * acpi_find_matche
    1.16          gdprintk(XENLOG_INFO VTDPREFIX, 
    1.17                   "acpi_find_matched_drhd_unit:include_all_drhd->addr = %lx\n",
    1.18                   include_all_drhd->address);
    1.19 -        return include_all_drhd;;
    1.20 +        return include_all_drhd;
    1.21      }
    1.22  
    1.23      return NULL;
    1.24 @@ -513,7 +517,7 @@ static int __init acpi_parse_dmar(unsign
    1.25              ret = acpi_parse_one_rmrr(entry_header);
    1.26              break;
    1.27          case ACPI_DMAR_ATSR:
    1.28 -            printk(KERN_INFO PREFIX "found ACPI_DMAR_RMRR\n");
    1.29 +            printk(KERN_INFO PREFIX "found ACPI_DMAR_ATSR\n");
    1.30              ret = acpi_parse_one_atsr(entry_header);
    1.31              break;
    1.32          default:
     2.1 --- a/xen/arch/x86/hvm/vmx/vtd/intel-iommu.c	Wed Jan 09 10:32:13 2008 +0000
     2.2 +++ b/xen/arch/x86/hvm/vmx/vtd/intel-iommu.c	Wed Jan 09 10:35:52 2008 +0000
     2.3 @@ -528,7 +528,6 @@ void iommu_flush_all(void)
     2.4  {
     2.5      struct acpi_drhd_unit *drhd;
     2.6      struct iommu *iommu;
     2.7 -    int i = 0;
     2.8  
     2.9      wbinvd();
    2.10      for_each_drhd_unit ( drhd )
    2.11 @@ -536,7 +535,6 @@ void iommu_flush_all(void)
    2.12          iommu = drhd->iommu;
    2.13          iommu_flush_context_global(iommu, 0);
    2.14          iommu_flush_iotlb_global(iommu, 0);
    2.15 -        i++;
    2.16      }
    2.17  }
    2.18  
     3.1 --- a/xen/arch/x86/hvm/vmx/vtd/utils.c	Wed Jan 09 10:32:13 2008 +0000
     3.2 +++ b/xen/arch/x86/hvm/vmx/vtd/utils.c	Wed Jan 09 10:35:52 2008 +0000
     3.3 @@ -154,8 +154,9 @@ void print_vtd_entries(struct domain *d,
     3.4      struct iommu *iommu;
     3.5      struct context_entry *ctxt_entry;
     3.6      struct root_entry *root_entry;
     3.7 -    u64 *l4 = NULL, *l3, *l2, *l1;
     3.8 -    u32 l4_index = 0, l3_index, l2_index, l1_index;
     3.9 +    struct dma_pte pte;
    3.10 +    u64 *l;
    3.11 +    u32 l_index;
    3.12      u32 i = 0;
    3.13      int level = agaw_to_level(hd->agaw);
    3.14  
    3.15 @@ -176,20 +177,17 @@ void print_vtd_entries(struct domain *d,
    3.16  
    3.17          iommu = drhd->iommu;
    3.18          root_entry = iommu->root_entry;
    3.19 -        printk("    root_entry = %p\n", root_entry);
    3.20          if ( root_entry == NULL )
    3.21          {
    3.22              printk("    root_entry == NULL\n");
    3.23              continue;
    3.24          }
    3.25  
    3.26 +        printk("    root_entry = %p\n", root_entry);
    3.27          printk("    root_entry[%x] = %"PRIx64"\n", bus, root_entry[bus].val);
    3.28 -        printk("    maddr_to_virt(root_entry[%x]) = %p\n",
    3.29 -               bus, maddr_to_virt(root_entry[bus].val));
    3.30 -
    3.31 -        if ( root_entry[bus].val == 0 )
    3.32 +        if ( !root_present(root_entry[bus]) )
    3.33          {
    3.34 -            printk("    root_entry[%x].lo == 0\n", bus);
    3.35 +            printk("    root_entry[%x] not present\n", bus);
    3.36              continue;
    3.37          }
    3.38  
    3.39 @@ -201,73 +199,44 @@ void print_vtd_entries(struct domain *d,
    3.40              continue;
    3.41          }
    3.42  
    3.43 -        if ( ctxt_entry[devfn].lo == 0 )
    3.44 -        {
    3.45 -            printk("    ctxt_entry[%x].lo == 0\n", devfn);
    3.46 -            continue;
    3.47 -        }
    3.48 -
    3.49          printk("    context = %p\n", ctxt_entry);
    3.50          printk("    context[%x] = %"PRIx64" %"PRIx64"\n",
    3.51                 devfn, ctxt_entry[devfn].hi, ctxt_entry[devfn].lo);
    3.52 -        printk("    maddr_to_virt(context[%x].lo) = %p\n",
    3.53 -               devfn, maddr_to_virt(ctxt_entry[devfn].lo));
    3.54 -        printk("    context[%x] = %"PRIx64"\n", devfn, ctxt_entry[devfn].lo);
    3.55 -
    3.56 -        switch ( level )
    3.57 +        if ( !context_present(ctxt_entry[devfn]) )
    3.58          {
    3.59 -        case VTD_PAGE_TABLE_LEVEL_3:
    3.60 -            l3 = maddr_to_virt(ctxt_entry[devfn].lo);
    3.61 -            l3 = (u64*)(((unsigned long)l3 >> PAGE_SHIFT_4K) << PAGE_SHIFT_4K);
    3.62 -            printk("    l3 = %p\n", l3);
    3.63 -            if ( l3 == NULL )
    3.64 -                continue;
    3.65 -            l3_index = get_level_index(gmfn, 3);
    3.66 -            printk("    l3_index = %x\n", l3_index);
    3.67 -            printk("    l3[%x] = %"PRIx64"\n", l3_index, l3[l3_index]);
    3.68 +            printk("    ctxt_entry[%x] not present\n", devfn);
    3.69 +            continue;
    3.70 +        }
    3.71  
    3.72 -            break;
    3.73 -        case VTD_PAGE_TABLE_LEVEL_4:
    3.74 -            l4 = maddr_to_virt(ctxt_entry[devfn].lo);
    3.75 -            l4 = (u64*)(((unsigned long)l4 >> PAGE_SHIFT_4K) << PAGE_SHIFT_4K);
    3.76 -            printk("    l4 = %p\n", l4);
    3.77 -            if ( l4 == NULL )
    3.78 -                continue;
    3.79 -            l4_index = get_level_index(gmfn, 4);
    3.80 -            printk("    l4_index = %x\n", l4_index);
    3.81 -            printk("    l4[%x] = %"PRIx64"\n", l4_index, l4[l4_index]);
    3.82 -
    3.83 -            l3 = maddr_to_virt(l4[l4_index]);
    3.84 -            l3 = (u64*)(((unsigned long)l3 >> PAGE_SHIFT_4K) << PAGE_SHIFT_4K);
    3.85 -            printk("    l3 = %p\n", l3);
    3.86 -            if ( l3 == NULL )
    3.87 -                continue;
    3.88 -            l3_index = get_level_index(gmfn, 3);
    3.89 -            printk("    l3_index = %x\n", l3_index);
    3.90 -            printk("    l3[%x] = %"PRIx64"\n", l3_index, l3[l3_index]);
    3.91 -
    3.92 -            break;
    3.93 -        default:
    3.94 +        if ( level != VTD_PAGE_TABLE_LEVEL_3 &&
    3.95 +             level != VTD_PAGE_TABLE_LEVEL_4)
    3.96 +        {
    3.97              printk("Unsupported VTD page table level (%d)!\n", level);
    3.98              continue;
    3.99          }
   3.100  
   3.101 -        l2 = maddr_to_virt(l3[l3_index]);
   3.102 -        l2 = (u64*)(((unsigned long)l2 >> PAGE_SHIFT_4K) << PAGE_SHIFT_4K);
   3.103 -        printk("    l2 = %p\n", l2);
   3.104 -        if ( l2 == NULL )
   3.105 -            continue;
   3.106 -        l2_index = get_level_index(gmfn, 2);
   3.107 -        printk("    l2_index = %x\n", l2_index);
   3.108 -        printk("    l2[%x] = %"PRIx64"\n", l2_index, l2[l2_index]);
   3.109 +        l = maddr_to_virt(ctxt_entry[devfn].lo);
   3.110 +        do
   3.111 +        {
   3.112 +            l = (u64*)(((unsigned long)l >> PAGE_SHIFT_4K) << PAGE_SHIFT_4K);
   3.113 +            printk("    l%d = %p\n", level, l);
   3.114 +            if ( l == NULL )
   3.115 +            {
   3.116 +                printk("    l%d == NULL\n", level);
   3.117 +                break;
   3.118 +            }
   3.119 +            l_index = get_level_index(gmfn, level);
   3.120 +            printk("    l%d_index = %x\n", level, l_index);
   3.121 +            printk("    l%d[%x] = %"PRIx64"\n", level, l_index, l[l_index]);
   3.122  
   3.123 -        l1 = maddr_to_virt(l2[l2_index]);
   3.124 -        l1 = (u64*)(((unsigned long)l1 >> PAGE_SHIFT_4K) << PAGE_SHIFT_4K);
   3.125 -        printk("    l1 = %p\n", l1);
   3.126 -        if ( l1 == NULL )
   3.127 -            continue;
   3.128 -        l1_index = get_level_index(gmfn, 1);
   3.129 -        printk("    l1_index = %x\n", l1_index);
   3.130 -        printk("    l1[%x] = %"PRIx64"\n", l1_index, l1[l1_index]);
   3.131 -   }
   3.132 +            pte.val = l[l_index];
   3.133 +            if ( !dma_pte_present(pte) )
   3.134 +            {
   3.135 +                printk("    l%d[%x] not present\n", level, l_index);
   3.136 +                break;
   3.137 +            }
   3.138 +
   3.139 +            l = maddr_to_virt(l[l_index]);
   3.140 +        } while ( --level );
   3.141 +    }
   3.142  }