ia64/xen-unstable

changeset 18130:fc44e35b3913

x86: Fix the dom0 booting hang when VT-d is enabled.

Dom0 C/S 593 hooks the pci bus probe and remove function. When
probing a function at booting time, it will first add the device into
Dom0's list through a hypercall, then execute the driver's probe
function. If the probe function fails, another hypercall is called to
remove the device from Dom0's list. But for some RMRR devices, for
example, USB devices, they may still be in use for some operation by
BIOS at booting time. So when removing those kind of devices, we
should still keep the RMRR information.

Also add a small fix for "for_each_rmrr_device".

Signed-off-by: Dongxiao Xu <dongxiao.xu@intel.com>
Signed-off-by: Weidong Han <weidong.han@intel.com>
Signed-off-by: Yunhong Jiang <yunhong.jiang@intel.com>
author Keir Fraser <keir.fraser@citrix.com>
date Tue Jul 22 11:56:26 2008 +0100 (2008-07-22)
parents 0bf73f557f41
children a637c023e066
files xen/drivers/passthrough/vtd/dmar.h xen/drivers/passthrough/vtd/iommu.c
line diff
     1.1 --- a/xen/drivers/passthrough/vtd/dmar.h	Tue Jul 22 11:55:06 2008 +0100
     1.2 +++ b/xen/drivers/passthrough/vtd/dmar.h	Tue Jul 22 11:56:26 2008 +0100
     1.3 @@ -76,7 +76,7 @@ struct acpi_atsr_unit {
     1.4  #define for_each_rmrr_device(rmrr, bdf, idx)            \
     1.5      list_for_each_entry(rmrr, &acpi_rmrr_units, list)   \
     1.6          /* assume there never is a bdf == 0 */          \
     1.7 -        for (idx = 0; (bdf = rmrr->scope.devices[i]) && \
     1.8 +        for (idx = 0; (bdf = rmrr->scope.devices[idx]) && \
     1.9                   idx < rmrr->scope.devices_cnt; idx++)
    1.10  
    1.11  struct acpi_drhd_unit * acpi_find_matched_drhd_unit(u8 bus, u8 devfn);
     2.1 --- a/xen/drivers/passthrough/vtd/iommu.c	Tue Jul 22 11:55:06 2008 +0100
     2.2 +++ b/xen/drivers/passthrough/vtd/iommu.c	Tue Jul 22 11:56:26 2008 +0100
     2.3 @@ -1294,11 +1294,18 @@ static int domain_context_mapping(struct
     2.4      return ret;
     2.5  }
     2.6  
     2.7 -static int domain_context_unmap_one(struct iommu *iommu, u8 bus, u8 devfn)
     2.8 +static int domain_context_unmap_one(
     2.9 +    struct domain *domain,
    2.10 +    struct iommu *iommu,
    2.11 +    u8 bus, u8 devfn)
    2.12  {
    2.13      struct context_entry *context, *context_entries;
    2.14      unsigned long flags;
    2.15      u64 maddr;
    2.16 +    struct acpi_rmrr_unit *rmrr;
    2.17 +    u16 bdf;
    2.18 +    int i;
    2.19 +    unsigned int is_rmrr_device = 0;
    2.20  
    2.21      maddr = bus_to_context_maddr(iommu, bus);
    2.22      context_entries = (struct context_entry *)map_vtd_domain_page(maddr);
    2.23 @@ -1311,18 +1318,32 @@ static int domain_context_unmap_one(stru
    2.24      }
    2.25  
    2.26      spin_lock_irqsave(&iommu->lock, flags);
    2.27 -    context_clear_present(*context);
    2.28 -    context_clear_entry(*context);
    2.29 -    iommu_flush_cache_entry(context);
    2.30 -    iommu_flush_context_global(iommu, 0);
    2.31 -    iommu_flush_iotlb_global(iommu, 0);
    2.32 +    if ( domain->domain_id == 0 )
    2.33 +    {
    2.34 +        for_each_rmrr_device ( rmrr, bdf, i )
    2.35 +        {
    2.36 +            if ( PCI_BUS(bdf) == bus && PCI_DEVFN2(bdf) == devfn )
    2.37 +            {
    2.38 +                is_rmrr_device = 1;
    2.39 +                break;
    2.40 +            }
    2.41 +        }
    2.42 +    }
    2.43 +    if ( !is_rmrr_device )
    2.44 +    {
    2.45 +        context_clear_present(*context);
    2.46 +        context_clear_entry(*context);
    2.47 +        iommu_flush_cache_entry(context);
    2.48 +        iommu_flush_context_domain(iommu, domain_iommu_domid(domain), 0);
    2.49 +        iommu_flush_iotlb_dsi(iommu, domain_iommu_domid(domain), 0);
    2.50 +    }
    2.51      unmap_vtd_domain_page(context_entries);
    2.52      spin_unlock_irqrestore(&iommu->lock, flags);
    2.53  
    2.54      return 0;
    2.55  }
    2.56  
    2.57 -static int domain_context_unmap(u8 bus, u8 devfn)
    2.58 +static int domain_context_unmap(struct domain *domain, u8 bus, u8 devfn)
    2.59  {
    2.60      struct acpi_drhd_unit *drhd;
    2.61      u16 sec_bus, sub_bus;
    2.62 @@ -1345,18 +1366,18 @@ static int domain_context_unmap(u8 bus, 
    2.63                                   PCI_SUBORDINATE_BUS);
    2.64          /*dmar_scope_remove_buses(&drhd->scope, sec_bus, sub_bus);*/
    2.65          if ( DEV_TYPE_PCI_BRIDGE )
    2.66 -            ret = domain_context_unmap_one(drhd->iommu, bus, devfn);
    2.67 +            ret = domain_context_unmap_one(domain, drhd->iommu, bus, devfn);
    2.68          break;
    2.69  
    2.70      case DEV_TYPE_PCIe_ENDPOINT:
    2.71 -        ret = domain_context_unmap_one(drhd->iommu, bus, devfn);
    2.72 +        ret = domain_context_unmap_one(domain, drhd->iommu, bus, devfn);
    2.73          break;
    2.74  
    2.75      case DEV_TYPE_PCI:
    2.76          if ( find_pcie_endpoint(&bus, &devfn, &secbus) )
    2.77 -            ret = domain_context_unmap_one(drhd->iommu, bus, devfn);
    2.78 +            ret = domain_context_unmap_one(domain, drhd->iommu, bus, devfn);
    2.79          if ( bus != secbus )
    2.80 -            domain_context_unmap_one(drhd->iommu, secbus, 0);
    2.81 +            domain_context_unmap_one(domain, drhd->iommu, secbus, 0);
    2.82          break;
    2.83  
    2.84      default:
    2.85 @@ -1386,7 +1407,7 @@ static int reassign_device_ownership(
    2.86  
    2.87      drhd = acpi_find_matched_drhd_unit(bus, devfn);
    2.88      pdev_iommu = drhd->iommu;
    2.89 -    domain_context_unmap(bus, devfn);
    2.90 +    domain_context_unmap(source, bus, devfn);
    2.91  
    2.92      write_lock(&pcidevs_lock);
    2.93      list_move(&pdev->domain_list, &target->arch.pdev_list);
    2.94 @@ -1584,7 +1605,9 @@ static int intel_iommu_add_device(struct
    2.95  
    2.96  static int intel_iommu_remove_device(struct pci_dev *pdev)
    2.97  {
    2.98 -    return domain_context_unmap(pdev->bus, pdev->devfn);
    2.99 +    if ( !pdev->domain )
   2.100 +        return -EINVAL;
   2.101 +    return domain_context_unmap(pdev->domain, pdev->bus, pdev->devfn);
   2.102  }
   2.103  
   2.104  static void setup_dom0_devices(struct domain *d)