debuggers.hg

changeset 18064:27aaff984b36

vt-d: Fixup when mapping devices on non-PCIe buses

The source-id for transactions on non-PCIe buses seem to originate
from devfn=0 on the secondary bus behind the bridge. Map that ID as
well when assigning the device. The ID to use in these scenarios is
not particularly well documented anywhere.

Signed-off-by: Espen Skoglund <espen.skoglund@netronome.com>
author Keir Fraser <keir.fraser@citrix.com>
date Thu Jul 10 17:33:23 2008 +0100 (2008-07-10)
parents 07c7aef164cf
children b41e07aa555a
files xen/drivers/passthrough/vtd/iommu.c
line diff
     1.1 --- a/xen/drivers/passthrough/vtd/iommu.c	Thu Jul 10 17:29:06 2008 +0100
     1.2 +++ b/xen/drivers/passthrough/vtd/iommu.c	Thu Jul 10 17:33:23 2008 +0100
     1.3 @@ -1186,9 +1186,10 @@ int pdev_type(u8 bus, u8 devfn)
     1.4  #define MAX_BUSES 256
     1.5  static struct { u8 map, bus, devfn; } bus2bridge[MAX_BUSES];
     1.6  
     1.7 -static int find_pcie_endpoint(u8 *bus, u8 *devfn)
     1.8 +static int find_pcie_endpoint(u8 *bus, u8 *devfn, u8 *secbus)
     1.9  {
    1.10      int cnt = 0;
    1.11 +    *secbus = *bus;
    1.12  
    1.13      if ( *bus == 0 )
    1.14          /* assume integrated PCI devices in RC have valid requester-id */
    1.15 @@ -1199,6 +1200,7 @@ static int find_pcie_endpoint(u8 *bus, u
    1.16  
    1.17      while ( bus2bridge[*bus].map )
    1.18      {
    1.19 +        *secbus = *bus;
    1.20          *devfn = bus2bridge[*bus].devfn;
    1.21          *bus = bus2bridge[*bus].bus;
    1.22          if ( cnt++ >= MAX_BUSES )
    1.23 @@ -1214,6 +1216,7 @@ static int domain_context_mapping(struct
    1.24      int ret = 0;
    1.25      u16 sec_bus, sub_bus, ob, odf;
    1.26      u32 type;
    1.27 +    u8 secbus;
    1.28  
    1.29      drhd = acpi_find_matched_drhd_unit(bus, devfn);
    1.30      if ( !drhd )
    1.31 @@ -1254,7 +1257,7 @@ static int domain_context_mapping(struct
    1.32                   bus, PCI_SLOT(devfn), PCI_FUNC(devfn));
    1.33  
    1.34          ob = bus; odf = devfn;
    1.35 -        if ( !find_pcie_endpoint(&bus, &devfn) )
    1.36 +        if ( !find_pcie_endpoint(&bus, &devfn, &secbus) )
    1.37          {
    1.38              gdprintk(XENLOG_WARNING VTDPREFIX, "domain_context_mapping:invalid");
    1.39              break;
    1.40 @@ -1265,7 +1268,17 @@ static int domain_context_mapping(struct
    1.41                       "domain_context_mapping:map:  bdf = %x:%x.%x -> %x:%x.%x\n",
    1.42                       ob, PCI_SLOT(odf), PCI_FUNC(odf),
    1.43                       bus, PCI_SLOT(devfn), PCI_FUNC(devfn));
    1.44 +
    1.45          ret = domain_context_mapping_one(domain, drhd->iommu, bus, devfn);
    1.46 +        if ( secbus != bus )
    1.47 +            /*
    1.48 +             * The source-id for transactions on non-PCIe buses seem
    1.49 +             * to originate from devfn=0 on the secondary bus behind
    1.50 +             * the bridge.  Map that id as well.  The id to use in
    1.51 +             * these scanarios is not particularly well documented
    1.52 +             * anywhere.
    1.53 +             */
    1.54 +            domain_context_mapping_one(domain, drhd->iommu, secbus, 0);
    1.55          break;
    1.56  
    1.57      default:
    1.58 @@ -1313,6 +1326,7 @@ static int domain_context_unmap(u8 bus, 
    1.59      u16 sec_bus, sub_bus;
    1.60      int ret = 0;
    1.61      u32 type;
    1.62 +    u8 secbus;
    1.63  
    1.64      drhd = acpi_find_matched_drhd_unit(bus, devfn);
    1.65      if ( !drhd )
    1.66 @@ -1337,8 +1351,10 @@ static int domain_context_unmap(u8 bus, 
    1.67          break;
    1.68  
    1.69      case DEV_TYPE_PCI:
    1.70 -        if ( find_pcie_endpoint(&bus, &devfn) )
    1.71 +        if ( find_pcie_endpoint(&bus, &devfn, &secbus) )
    1.72              ret = domain_context_unmap_one(drhd->iommu, bus, devfn);
    1.73 +        if ( bus != secbus )
    1.74 +            domain_context_unmap_one(drhd->iommu, secbus, 0);
    1.75          break;
    1.76  
    1.77      default:
    1.78 @@ -1776,7 +1792,8 @@ int intel_iommu_assign_device(struct dom
    1.79  
    1.80  static int intel_iommu_group_id(u8 bus, u8 devfn)
    1.81  {
    1.82 -    if ( !bus2bridge[bus].map || find_pcie_endpoint(&bus, &devfn) )
    1.83 +    u8 secbus;
    1.84 +    if ( !bus2bridge[bus].map || find_pcie_endpoint(&bus, &devfn, &secbus) )
    1.85          return PCI_BDF2(bus, devfn);
    1.86      else
    1.87          return -1;