ia64/xen-unstable

changeset 17975:bd7f2a120f94

Restructure VT-d device scope and PCI bridge handling

Create a bitmap for each device scope indicating which buses are
covered by the scope. Upon mapping PCI-PCI bridges we now detect
whether we have a bridge to a non-PCIe bus. If so, all devices mapped
on that bus are squashed to the requester-id of the bridge. Bridges
to PCIe busses are ignored. The requester-id squashing also
determines the iommu device group id for the device.

Signed-off-by: Espen Skoglund <espen.skoglund@netronome.com>
author Keir Fraser <keir.fraser@citrix.com>
date Fri Jul 04 17:51:42 2008 +0100 (2008-07-04)
parents 1e9df5cb885f
children 7f7d0e7aa01b
files xen/drivers/passthrough/vtd/dmar.c xen/drivers/passthrough/vtd/dmar.h xen/drivers/passthrough/vtd/intremap.c xen/drivers/passthrough/vtd/iommu.c xen/drivers/passthrough/vtd/utils.c xen/include/xen/pci.h
line diff
     1.1 --- a/xen/drivers/passthrough/vtd/dmar.c	Fri Jul 04 17:51:16 2008 +0100
     1.2 +++ b/xen/drivers/passthrough/vtd/dmar.c	Fri Jul 04 17:51:42 2008 +0100
     1.3 @@ -45,6 +45,26 @@ LIST_HEAD(acpi_atsr_units);
     1.4  
     1.5  u8 dmar_host_address_width;
     1.6  
     1.7 +void dmar_scope_add_buses(struct dmar_scope *scope, u16 sec_bus, u16 sub_bus)
     1.8 +{
     1.9 +    sub_bus &= 0xff;
    1.10 +    if (sec_bus > sub_bus)
    1.11 +        return;
    1.12 +
    1.13 +    while ( sec_bus <= sub_bus )
    1.14 +        set_bit(sec_bus++, scope->buses);
    1.15 +}
    1.16 +
    1.17 +void dmar_scope_remove_buses(struct dmar_scope *scope, u16 sec_bus, u16 sub_bus)
    1.18 +{
    1.19 +    sub_bus &= 0xff;
    1.20 +    if (sec_bus > sub_bus)
    1.21 +        return;
    1.22 +
    1.23 +    while ( sec_bus <= sub_bus )
    1.24 +        clear_bit(sec_bus++, scope->buses);
    1.25 +}
    1.26 +
    1.27  static int __init acpi_register_drhd_unit(struct acpi_drhd_unit *drhd)
    1.28  {
    1.29      /*
    1.30 @@ -94,21 +114,6 @@ struct iommu * ioapic_to_iommu(unsigned 
    1.31      return NULL;
    1.32  }
    1.33  
    1.34 -static int acpi_pci_device_match(struct pci_dev *devices, int cnt,
    1.35 -                                 struct pci_dev *dev)
    1.36 -{
    1.37 -    int i;
    1.38 -
    1.39 -    for ( i = 0; i < cnt; i++ )
    1.40 -    {
    1.41 -        if ( (dev->bus == devices->bus) &&
    1.42 -             (dev->devfn == devices->devfn) )
    1.43 -            return 1;
    1.44 -        devices++;
    1.45 -    }
    1.46 -    return 0;
    1.47 -}
    1.48 -
    1.49  static int __init acpi_register_atsr_unit(struct acpi_atsr_unit *atsr)
    1.50  {
    1.51      /*
    1.52 @@ -122,39 +127,36 @@ static int __init acpi_register_atsr_uni
    1.53      return 0;
    1.54  }
    1.55  
    1.56 -struct acpi_drhd_unit * acpi_find_matched_drhd_unit(struct pci_dev *dev)
    1.57 +struct acpi_drhd_unit * acpi_find_matched_drhd_unit(u8 bus, u8 devfn)
    1.58  {
    1.59      struct acpi_drhd_unit *drhd;
    1.60 -    struct acpi_drhd_unit *include_all_drhd;
    1.61 +    struct acpi_drhd_unit *found = NULL, *include_all = NULL;
    1.62 +    int i;
    1.63  
    1.64 -    include_all_drhd = NULL;
    1.65      list_for_each_entry ( drhd, &acpi_drhd_units, list )
    1.66      {
    1.67 +        for (i = 0; i < drhd->scope.devices_cnt; i++)
    1.68 +            if ( drhd->scope.devices[i] == PCI_BDF2(bus, devfn) )
    1.69 +                return drhd;
    1.70 +
    1.71 +        if ( test_bit(bus, drhd->scope.buses) )
    1.72 +            found = drhd;
    1.73 +
    1.74          if ( drhd->include_all )
    1.75 -        {
    1.76 -            include_all_drhd = drhd;
    1.77 -            continue;
    1.78 -        }
    1.79 -
    1.80 -        if ( acpi_pci_device_match(drhd->devices,
    1.81 -                                   drhd->devices_cnt, dev) )
    1.82 -            return drhd;
    1.83 +            include_all = drhd;
    1.84      }
    1.85  
    1.86 -    if ( include_all_drhd )
    1.87 -        return include_all_drhd;
    1.88 -
    1.89 -    return NULL;
    1.90 +    return found ? found : include_all;
    1.91  }
    1.92  
    1.93 +/*
    1.94 + * Count number of devices in device scope.  Do not include PCI sub
    1.95 + * hierarchies.
    1.96 + */
    1.97  static int scope_device_count(void *start, void *end)
    1.98  {
    1.99      struct acpi_dev_scope *scope;
   1.100 -    u16 bus, sub_bus, sec_bus;
   1.101 -    struct acpi_pci_path *path;
   1.102 -    int depth, count = 0;
   1.103 -    u8 dev, func;
   1.104 -    u32 l;
   1.105 +    int count = 0;
   1.106  
   1.107      while ( start < end )
   1.108      {
   1.109 @@ -162,73 +164,14 @@ static int scope_device_count(void *star
   1.110          if ( (scope->length < MIN_SCOPE_LEN) ||
   1.111               (scope->dev_type >= ACPI_DEV_ENTRY_COUNT) )
   1.112          {
   1.113 -            dprintk(XENLOG_WARNING VTDPREFIX, "Invalid device scope\n");
   1.114 +            dprintk(XENLOG_WARNING VTDPREFIX, "Invalid device scope.\n");
   1.115              return -EINVAL;
   1.116          }
   1.117  
   1.118 -        path = (struct acpi_pci_path *)(scope + 1);
   1.119 -        bus = scope->start_bus;
   1.120 -        depth = (scope->length - sizeof(struct acpi_dev_scope))
   1.121 -		    / sizeof(struct acpi_pci_path);
   1.122 -        while ( --depth > 0 )
   1.123 -        {
   1.124 -            bus = pci_conf_read8(
   1.125 -                bus, path->dev, path->fn, PCI_SECONDARY_BUS);
   1.126 -            path++;
   1.127 -        }
   1.128 -
   1.129 -        if ( scope->dev_type == ACPI_DEV_ENDPOINT )
   1.130 -        {
   1.131 -            dprintk(XENLOG_INFO VTDPREFIX,
   1.132 -                    "found endpoint: bdf = %x:%x:%x\n",
   1.133 -                    bus, path->dev, path->fn);
   1.134 +        if ( scope->dev_type == ACPI_DEV_ENDPOINT ||
   1.135 +             scope->dev_type == ACPI_DEV_IOAPIC ||
   1.136 +             scope->dev_type == ACPI_DEV_MSI_HPET )
   1.137              count++;
   1.138 -        }
   1.139 -        else if ( scope->dev_type == ACPI_DEV_P2PBRIDGE )
   1.140 -        {
   1.141 -            dprintk(XENLOG_INFO VTDPREFIX,
   1.142 -                    "found bridge: bdf = %x:%x:%x\n",
   1.143 -                    bus, path->dev, path->fn);
   1.144 -            sec_bus = pci_conf_read8(
   1.145 -                bus, path->dev, path->fn, PCI_SECONDARY_BUS);
   1.146 -            sub_bus = pci_conf_read8(
   1.147 -                bus, path->dev, path->fn, PCI_SUBORDINATE_BUS);
   1.148 -
   1.149 -            while ( sec_bus <= sub_bus )
   1.150 -            {
   1.151 -                for ( dev = 0; dev < 32; dev++ )
   1.152 -                {
   1.153 -                    for ( func = 0; func < 8; func++ )
   1.154 -                    {
   1.155 -                        l = pci_conf_read32(
   1.156 -                            sec_bus, dev, func, PCI_VENDOR_ID);
   1.157 -
   1.158 -                        /* some broken boards return 0 or
   1.159 -                         * ~0 if a slot is empty
   1.160 -                         */
   1.161 -                        if ( l == 0xffffffff || l == 0x00000000 ||
   1.162 -                             l == 0x0000ffff || l == 0xffff0000 )
   1.163 -                            break;
   1.164 -                        count++;
   1.165 -                    }
   1.166 -                }
   1.167 -                sec_bus++;
   1.168 -            }
   1.169 -        }
   1.170 -        else if ( scope->dev_type == ACPI_DEV_IOAPIC )
   1.171 -        {
   1.172 -            dprintk(XENLOG_INFO VTDPREFIX,
   1.173 -                    "found IOAPIC: bdf = %x:%x:%x\n",
   1.174 -                    bus, path->dev, path->fn);
   1.175 -            count++;
   1.176 -        }
   1.177 -        else
   1.178 -        {
   1.179 -            dprintk(XENLOG_INFO VTDPREFIX,
   1.180 -                    "found MSI HPET: bdf = %x:%x:%x\n",
   1.181 -                    bus, path->dev, path->fn);
   1.182 -            count++;
   1.183 -        }
   1.184  
   1.185          start += scope->length;
   1.186      }
   1.187 @@ -236,132 +179,96 @@ static int scope_device_count(void *star
   1.188      return count;
   1.189  }
   1.190  
   1.191 -static int __init acpi_parse_dev_scope(
   1.192 -    void *start, void *end, void *acpi_entry, int type)
   1.193 +
   1.194 +static int __init acpi_parse_dev_scope(void *start, void *end,
   1.195 +                                       void *acpi_entry, int type)
   1.196  {
   1.197 -    struct acpi_dev_scope *scope;
   1.198 +    struct dmar_scope *scope = acpi_entry;
   1.199 +    struct acpi_ioapic_unit *acpi_ioapic_unit;
   1.200 +    struct acpi_dev_scope *acpi_scope;
   1.201      u16 bus, sub_bus, sec_bus;
   1.202      struct acpi_pci_path *path;
   1.203 -    struct acpi_ioapic_unit *acpi_ioapic_unit = NULL;
   1.204 -    int depth;
   1.205 -    struct pci_dev *pdev;
   1.206 -    u8 dev, func;
   1.207 -    u32 l;
   1.208 +    int depth, cnt, didx = 0;
   1.209  
   1.210 -    int *cnt = NULL;
   1.211 -    struct pci_dev **devices = NULL;
   1.212 -    struct acpi_drhd_unit *dmaru = (struct acpi_drhd_unit *) acpi_entry;
   1.213 -    struct acpi_rmrr_unit *rmrru = (struct acpi_rmrr_unit *) acpi_entry;
   1.214 -    struct acpi_atsr_unit *atsru = (struct acpi_atsr_unit *) acpi_entry;
   1.215 +    if ( (cnt = scope_device_count(start, end)) < 0 )
   1.216 +        return cnt;
   1.217  
   1.218 -    switch (type) {
   1.219 -        case DMAR_TYPE:
   1.220 -            cnt = &(dmaru->devices_cnt);
   1.221 -            devices = &(dmaru->devices);
   1.222 -            break;
   1.223 -        case RMRR_TYPE:
   1.224 -            cnt = &(rmrru->devices_cnt);
   1.225 -            devices = &(rmrru->devices);
   1.226 -            break;
   1.227 -        case ATSR_TYPE:
   1.228 -            cnt = &(atsru->devices_cnt);
   1.229 -            devices = &(atsru->devices);
   1.230 -            break;
   1.231 -        default:
   1.232 -            dprintk(XENLOG_ERR VTDPREFIX, "invalid vt-d acpi entry type\n");
   1.233 +    scope->devices_cnt = cnt;
   1.234 +    if ( cnt > 0 )
   1.235 +    {
   1.236 +        scope->devices = xmalloc_array(u16, cnt);
   1.237 +        if ( !scope->devices )
   1.238 +            return -ENOMEM;
   1.239 +        memset(scope->devices, 0, sizeof(u16) * cnt);
   1.240      }
   1.241  
   1.242 -    *cnt = scope_device_count(start, end);
   1.243 -    if ( *cnt == 0 )
   1.244 -    {
   1.245 -        dprintk(XENLOG_INFO VTDPREFIX, "acpi_parse_dev_scope: no device\n");
   1.246 -        return 0;
   1.247 -    }
   1.248 -
   1.249 -    *devices = xmalloc_array(struct pci_dev,  *cnt);
   1.250 -    if ( !*devices )
   1.251 -        return -ENOMEM;
   1.252 -    memset(*devices, 0, sizeof(struct pci_dev) * (*cnt));
   1.253 -
   1.254 -    pdev = *devices;
   1.255      while ( start < end )
   1.256      {
   1.257 -        scope = start;
   1.258 -        path = (struct acpi_pci_path *)(scope + 1);
   1.259 -        depth = (scope->length - sizeof(struct acpi_dev_scope))
   1.260 +        acpi_scope = start;
   1.261 +        path = (struct acpi_pci_path *)(acpi_scope + 1);
   1.262 +        depth = (acpi_scope->length - sizeof(struct acpi_dev_scope))
   1.263  		    / sizeof(struct acpi_pci_path);
   1.264 -        bus = scope->start_bus;
   1.265 +        bus = acpi_scope->start_bus;
   1.266  
   1.267          while ( --depth > 0 )
   1.268          {
   1.269 -            bus = pci_conf_read8(
   1.270 -                bus, path->dev, path->fn, PCI_SECONDARY_BUS);
   1.271 +            bus = pci_conf_read8(bus, path->dev, path->fn, PCI_SECONDARY_BUS);
   1.272              path++;
   1.273          }
   1.274 +        
   1.275 +        switch ( acpi_scope->dev_type )
   1.276 +        {
   1.277 +        case ACPI_DEV_P2PBRIDGE:
   1.278 +        {
   1.279 +            sec_bus = pci_conf_read8(
   1.280 +		bus, path->dev, path->fn, PCI_SECONDARY_BUS);
   1.281 +            sub_bus = pci_conf_read8(
   1.282 +		bus, path->dev, path->fn, PCI_SUBORDINATE_BUS);
   1.283 +            dprintk(XENLOG_INFO VTDPREFIX,
   1.284 +                    "found bridge: bdf = %x:%x.%x  sec = %x  sub = %x\n",
   1.285 +                    bus, path->dev, path->fn, sec_bus, sub_bus);
   1.286 +
   1.287 +            dmar_scope_add_buses(scope, sec_bus, sub_bus);
   1.288 +            break;
   1.289 +        }
   1.290  
   1.291 -        if ( scope->dev_type == ACPI_DEV_ENDPOINT )
   1.292 -        {
   1.293 -            dprintk(XENLOG_INFO VTDPREFIX,
   1.294 -                    "found endpoint: bdf = %x:%x:%x\n",
   1.295 -                    bus, path->dev, path->fn);
   1.296 -            pdev->bus = bus;
   1.297 -            pdev->devfn = PCI_DEVFN(path->dev, path->fn);
   1.298 -            pdev++;
   1.299 -        }
   1.300 -        else if ( scope->dev_type == ACPI_DEV_P2PBRIDGE )
   1.301 -        {
   1.302 -            dprintk(XENLOG_INFO VTDPREFIX,
   1.303 -                    "found bridge: bus = %x dev = %x func = %x\n",
   1.304 +	case ACPI_DEV_MSI_HPET:
   1.305 +            dprintk(XENLOG_INFO VTDPREFIX, "found MSI HPET: bdf = %x:%x.%x\n",
   1.306                      bus, path->dev, path->fn);
   1.307 -            sec_bus = pci_conf_read8(
   1.308 -                bus, path->dev, path->fn, PCI_SECONDARY_BUS);
   1.309 -            sub_bus = pci_conf_read8(
   1.310 -                bus, path->dev, path->fn, PCI_SUBORDINATE_BUS);
   1.311 +            scope->devices[didx++] = PCI_BDF(bus, path->dev, path->fn);
   1.312 +            break;
   1.313  
   1.314 -            while ( sec_bus <= sub_bus )
   1.315 -            {
   1.316 -                for ( dev = 0; dev < 32; dev++ )
   1.317 -                {
   1.318 -                    for ( func = 0; func < 8; func++ )
   1.319 -                    {
   1.320 -                        l = pci_conf_read32(
   1.321 -                            sec_bus, dev, func, PCI_VENDOR_ID);
   1.322 +        case ACPI_DEV_ENDPOINT:
   1.323 +            dprintk(XENLOG_INFO VTDPREFIX, "found endpoint: bdf = %x:%x.%x\n",
   1.324 +                    bus, path->dev, path->fn);
   1.325 +            scope->devices[didx++] = PCI_BDF(bus, path->dev, path->fn);
   1.326 +            break;
   1.327 +
   1.328 +        case ACPI_DEV_IOAPIC:
   1.329 +        {
   1.330 +            dprintk(XENLOG_INFO VTDPREFIX, "found IOAPIC: bdf = %x:%x.%x\n",
   1.331 +                    bus, path->dev, path->fn);
   1.332  
   1.333 -                        /* some broken boards return 0 or
   1.334 -                         * ~0 if a slot is empty
   1.335 -                         */
   1.336 -                        if ( l == 0xffffffff || l == 0x00000000 ||
   1.337 -                             l == 0x0000ffff || l == 0xffff0000 )
   1.338 -                            break;
   1.339 +            if ( type == DMAR_TYPE )
   1.340 +            {
   1.341 +                struct acpi_drhd_unit *drhd = acpi_entry;
   1.342 +                acpi_ioapic_unit = xmalloc(struct acpi_ioapic_unit);
   1.343 +                if ( !acpi_ioapic_unit )
   1.344 +                    return -ENOMEM;
   1.345 +                acpi_ioapic_unit->apic_id = acpi_scope->enum_id;
   1.346 +                acpi_ioapic_unit->ioapic.bdf.bus = bus;
   1.347 +                acpi_ioapic_unit->ioapic.bdf.dev = path->dev;
   1.348 +                acpi_ioapic_unit->ioapic.bdf.func = path->fn;
   1.349 +                list_add(&acpi_ioapic_unit->list, &drhd->ioapic_list);
   1.350 +            }
   1.351  
   1.352 -                        pdev->bus = sec_bus;
   1.353 -                        pdev->devfn = PCI_DEVFN(dev, func);
   1.354 -                        pdev++;
   1.355 -                    }
   1.356 -                }
   1.357 -                sec_bus++;
   1.358 -            }
   1.359 +            scope->devices[didx++] = PCI_BDF(bus, path->dev, path->fn);
   1.360 +            break;
   1.361          }
   1.362 -        else if ( scope->dev_type == ACPI_DEV_IOAPIC )
   1.363 -        {
   1.364 -            acpi_ioapic_unit = xmalloc(struct acpi_ioapic_unit);
   1.365 -            if ( !acpi_ioapic_unit )
   1.366 -                return -ENOMEM;
   1.367 -            acpi_ioapic_unit->apic_id = scope->enum_id;
   1.368 -            acpi_ioapic_unit->ioapic.bdf.bus = bus;
   1.369 -            acpi_ioapic_unit->ioapic.bdf.dev = path->dev;
   1.370 -            acpi_ioapic_unit->ioapic.bdf.func = path->fn;
   1.371 -            list_add(&acpi_ioapic_unit->list, &dmaru->ioapic_list);
   1.372 -            dprintk(XENLOG_INFO VTDPREFIX,
   1.373 -                    "found IOAPIC: bus = %x dev = %x func = %x\n",
   1.374 -                    bus, path->dev, path->fn);
   1.375          }
   1.376 -        else
   1.377 -            dprintk(XENLOG_INFO VTDPREFIX,
   1.378 -                    "found MSI HPET: bus = %x dev = %x func = %x\n",
   1.379 -                    bus, path->dev, path->fn);
   1.380 -        start += scope->length;
   1.381 -    }
   1.382 +
   1.383 +        start += acpi_scope->length;
   1.384 +   }
   1.385  
   1.386      return 0;
   1.387  }
   1.388 @@ -370,10 +277,17 @@ static int __init
   1.389  acpi_parse_one_drhd(struct acpi_dmar_entry_header *header)
   1.390  {
   1.391      struct acpi_table_drhd * drhd = (struct acpi_table_drhd *)header;
   1.392 +    void *dev_scope_start, *dev_scope_end;
   1.393      struct acpi_drhd_unit *dmaru;
   1.394      int ret = 0;
   1.395 -    static int include_all;
   1.396 -    void *dev_scope_start, *dev_scope_end;
   1.397 +    static int include_all = 0;
   1.398 +
   1.399 +    if ( include_all )
   1.400 +    {
   1.401 +        dprintk(XENLOG_WARNING VTDPREFIX,
   1.402 +                "DMAR unit with INCLUDE_ALL is not not the last unit.\n");
   1.403 +        return -EINVAL;
   1.404 +    }
   1.405  
   1.406      dmaru = xmalloc(struct acpi_drhd_unit);
   1.407      if ( !dmaru )
   1.408 @@ -387,20 +301,13 @@ acpi_parse_one_drhd(struct acpi_dmar_ent
   1.409              dmaru->address);
   1.410  
   1.411      dev_scope_start = (void *)(drhd + 1);
   1.412 -    dev_scope_end   = ((void *)drhd) + header->length;
   1.413 +    dev_scope_end = ((void *)drhd) + header->length;
   1.414      ret = acpi_parse_dev_scope(dev_scope_start, dev_scope_end,
   1.415                                 dmaru, DMAR_TYPE);
   1.416  
   1.417      if ( dmaru->include_all )
   1.418      {
   1.419          dprintk(XENLOG_INFO VTDPREFIX, "found INCLUDE_ALL\n");
   1.420 -        /* Only allow one INCLUDE_ALL */
   1.421 -        if ( include_all )
   1.422 -        {
   1.423 -            dprintk(XENLOG_WARNING VTDPREFIX,
   1.424 -                    "Only one INCLUDE_ALL device scope is allowed\n");
   1.425 -            ret = -EINVAL;
   1.426 -        }
   1.427          include_all = 1;
   1.428      }
   1.429  
   1.430 @@ -430,7 +337,8 @@ acpi_parse_one_rmrr(struct acpi_dmar_ent
   1.431      dev_scope_end   = ((void *)rmrr) + header->length;
   1.432      ret = acpi_parse_dev_scope(dev_scope_start, dev_scope_end,
   1.433                                 rmrru, RMRR_TYPE);
   1.434 -    if ( ret || (rmrru->devices_cnt == 0) )
   1.435 +
   1.436 +    if ( ret || (rmrru->scope.devices_cnt == 0) )
   1.437          xfree(rmrru);
   1.438      else
   1.439          acpi_register_rmrr_unit(rmrru);
     2.1 --- a/xen/drivers/passthrough/vtd/dmar.h	Fri Jul 04 17:51:16 2008 +0100
     2.2 +++ b/xen/drivers/passthrough/vtd/dmar.h	Fri Jul 04 17:51:42 2008 +0100
     2.3 @@ -40,48 +40,48 @@ struct acpi_ioapic_unit {
     2.4      }ioapic;
     2.5  };
     2.6  
     2.7 +struct dmar_scope {
     2.8 +    DECLARE_BITMAP(buses, 256);         /* buses owned by this unit */
     2.9 +    u16    *devices;                    /* devices owned by this unit */
    2.10 +    int    devices_cnt;
    2.11 +};
    2.12 +
    2.13  struct acpi_drhd_unit {
    2.14 +    struct dmar_scope scope;            /* must be first member of struct */
    2.15      struct list_head list;
    2.16 -    u64    address; /* register base address of the unit */
    2.17 -    struct pci_dev *devices; /* target devices */
    2.18 -    int    devices_cnt;
    2.19 +    u64    address;                     /* register base address of the unit */
    2.20      u8     include_all:1;
    2.21      struct iommu *iommu;
    2.22      struct list_head ioapic_list;
    2.23  };
    2.24  
    2.25  struct acpi_rmrr_unit {
    2.26 +    struct dmar_scope scope;            /* must be first member of struct */
    2.27      struct list_head list;
    2.28      u64    base_address;
    2.29      u64    end_address;
    2.30 -    struct pci_dev *devices; /* target devices */
    2.31 -    int    devices_cnt;
    2.32      u8     allow_all:1;
    2.33  };
    2.34  
    2.35  struct acpi_atsr_unit {
    2.36 +    struct dmar_scope scope;            /* must be first member of struct */
    2.37      struct list_head list;
    2.38 -    struct pci_dev *devices; /* target devices */
    2.39 -    int    devices_cnt;
    2.40      u8     all_ports:1;
    2.41  };
    2.42  
    2.43 -#define for_each_iommu(domain, iommu) \
    2.44 -    list_for_each_entry(iommu, \
    2.45 -        &(domain->arch.hvm_domain.hvm_iommu.iommu_list), list)
    2.46  
    2.47  #define for_each_drhd_unit(drhd) \
    2.48      list_for_each_entry(drhd, &acpi_drhd_units, list)
    2.49 -#define for_each_rmrr_device(rmrr, pdev) \
    2.50 -    list_for_each_entry(rmrr, &acpi_rmrr_units, list) { \
    2.51 -        int _i; \
    2.52 -        for (_i = 0; _i < rmrr->devices_cnt; _i++) { \
    2.53 -            pdev = &(rmrr->devices[_i]);
    2.54 -#define end_for_each_rmrr_device(rmrr, pdev) \
    2.55 -        } \
    2.56 -    }
    2.57  
    2.58 -struct acpi_drhd_unit * acpi_find_matched_drhd_unit(struct pci_dev *dev);
    2.59 +#define for_each_rmrr_device(rmrr, bdf, idx)            \
    2.60 +    list_for_each_entry(rmrr, &acpi_rmrr_units, list)   \
    2.61 +        /* assume there never is a bdf == 0 */          \
    2.62 +        for (idx = 0; (bdf = rmrr->scope.devices[i]) && \
    2.63 +                 idx < rmrr->scope.devices_cnt; idx++)
    2.64 +
    2.65 +struct acpi_drhd_unit * acpi_find_matched_drhd_unit(u8 bus, u8 devfn);
    2.66 +void dmar_scope_add_buses(struct dmar_scope *scope, u16 sec, u16 sub);
    2.67 +void dmar_scope_remove_buses(struct dmar_scope *scope, u16 sec, u16 sub);
    2.68  
    2.69  #define DMAR_TYPE 1
    2.70  #define RMRR_TYPE 2
    2.71 @@ -91,6 +91,6 @@ struct acpi_drhd_unit * acpi_find_matche
    2.72  
    2.73  int vtd_hw_check(void);
    2.74  void disable_pmr(struct iommu *iommu);
    2.75 -int is_usb_device(struct pci_dev *pdev);
    2.76 +int is_usb_device(u8 bus, u8 devfn);
    2.77  
    2.78  #endif /* _DMAR_H_ */
     3.1 --- a/xen/drivers/passthrough/vtd/intremap.c	Fri Jul 04 17:51:16 2008 +0100
     3.2 +++ b/xen/drivers/passthrough/vtd/intremap.c	Fri Jul 04 17:51:42 2008 +0100
     3.3 @@ -396,7 +396,7 @@ void msi_msg_read_remap_rte(
     3.4      struct iommu *iommu = NULL;
     3.5      struct ir_ctrl *ir_ctrl;
     3.6  
     3.7 -    drhd = acpi_find_matched_drhd_unit(pdev);
     3.8 +    drhd = acpi_find_matched_drhd_unit(pdev->bus, pdev->devfn);
     3.9      iommu = drhd->iommu;
    3.10  
    3.11      ir_ctrl = iommu_ir_ctrl(iommu);
    3.12 @@ -414,7 +414,7 @@ void msi_msg_write_remap_rte(
    3.13      struct iommu *iommu = NULL;
    3.14      struct ir_ctrl *ir_ctrl;
    3.15  
    3.16 -    drhd = acpi_find_matched_drhd_unit(msi_desc->dev);
    3.17 +    drhd = acpi_find_matched_drhd_unit(pdev->bus, pdev->devfn);
    3.18      iommu = drhd->iommu;
    3.19  
    3.20      ir_ctrl = iommu_ir_ctrl(iommu);
     4.1 --- a/xen/drivers/passthrough/vtd/iommu.c	Fri Jul 04 17:51:16 2008 +0100
     4.2 +++ b/xen/drivers/passthrough/vtd/iommu.c	Fri Jul 04 17:51:42 2008 +0100
     4.3 @@ -1089,8 +1089,8 @@ static int domain_context_mapping_one(
     4.4      if ( ecap_pass_thru(iommu->ecap) && (domain->domain_id == 0) )
     4.5          context_set_translation_type(*context, CONTEXT_TT_PASS_THRU);
     4.6      else
     4.7 +#endif
     4.8      {
     4.9 -#endif
    4.10          /* Ensure we have pagetables allocated down to leaf PTE. */
    4.11          if ( hd->pgd_maddr == 0 )
    4.12          {
    4.13 @@ -1119,9 +1119,7 @@ static int domain_context_mapping_one(
    4.14  
    4.15          context_set_address_root(*context, pgd_maddr);
    4.16          context_set_translation_type(*context, CONTEXT_TT_MULTI_LEVEL);
    4.17 -#ifdef CONTEXT_PASSTHRU
    4.18      }
    4.19 -#endif
    4.20  
    4.21      /*
    4.22       * domain_id 0 is not valid on Intel's IOMMU, force domain_id to
    4.23 @@ -1150,115 +1148,128 @@ static int domain_context_mapping_one(
    4.24  #define PCI_BASE_CLASS_BRIDGE    0x06
    4.25  #define PCI_CLASS_BRIDGE_PCI     0x0604
    4.26  
    4.27 -#define DEV_TYPE_PCIe_ENDPOINT   1
    4.28 -#define DEV_TYPE_PCI_BRIDGE      2
    4.29 -#define DEV_TYPE_PCI             3
    4.30 +enum {
    4.31 +    DEV_TYPE_PCIe_ENDPOINT,
    4.32 +    DEV_TYPE_PCIe_BRIDGE,
    4.33 +    DEV_TYPE_PCI_BRIDGE,
    4.34 +    DEV_TYPE_PCI,
    4.35 +};
    4.36  
    4.37 -int pdev_type(struct pci_dev *dev)
    4.38 +int pdev_type(u8 bus, u8 devfn)
    4.39  {
    4.40      u16 class_device;
    4.41 -    u16 status;
    4.42 +    u16 status, creg;
    4.43 +    int pos;
    4.44 +    u8 d = PCI_SLOT(devfn), f = PCI_FUNC(devfn);
    4.45  
    4.46 -    class_device = pci_conf_read16(dev->bus, PCI_SLOT(dev->devfn),
    4.47 -                                   PCI_FUNC(dev->devfn), PCI_CLASS_DEVICE);
    4.48 +    class_device = pci_conf_read16(bus, d, f, PCI_CLASS_DEVICE);
    4.49      if ( class_device == PCI_CLASS_BRIDGE_PCI )
    4.50 -        return DEV_TYPE_PCI_BRIDGE;
    4.51 +    {
    4.52 +        pos = pci_find_next_cap(bus, devfn, PCI_CAPABILITY_LIST, PCI_CAP_ID_EXP);
    4.53 +        if ( !pos )
    4.54 +            return DEV_TYPE_PCI_BRIDGE;
    4.55 +        creg = pci_conf_read16(bus, d, f, pos + PCI_EXP_FLAGS);
    4.56 +        return ((creg & PCI_EXP_FLAGS_TYPE) >> 4) == PCI_EXP_TYPE_PCI_BRIDGE ?
    4.57 +            DEV_TYPE_PCI_BRIDGE : DEV_TYPE_PCIe_BRIDGE;
    4.58 +    }
    4.59  
    4.60 -    status = pci_conf_read16(dev->bus, PCI_SLOT(dev->devfn),
    4.61 -                             PCI_FUNC(dev->devfn), PCI_STATUS);
    4.62 -
    4.63 +    status = pci_conf_read16(bus, d, f, PCI_STATUS);
    4.64      if ( !(status & PCI_STATUS_CAP_LIST) )
    4.65          return DEV_TYPE_PCI;
    4.66  
    4.67 -    if ( pci_find_next_cap(dev->bus, dev->devfn,
    4.68 -                            PCI_CAPABILITY_LIST, PCI_CAP_ID_EXP) )
    4.69 +    if ( pci_find_next_cap(bus, devfn, PCI_CAPABILITY_LIST, PCI_CAP_ID_EXP) )
    4.70          return DEV_TYPE_PCIe_ENDPOINT;
    4.71  
    4.72      return DEV_TYPE_PCI;
    4.73  }
    4.74  
    4.75  #define MAX_BUSES 256
    4.76 -struct pci_dev bus2bridge[MAX_BUSES];
    4.77 +static struct { u8 map, bus, devfn; } bus2bridge[MAX_BUSES];
    4.78 +
    4.79 +static int find_pcie_endpoint(u8 *bus, u8 *devfn)
    4.80 +{
    4.81 +    int cnt = 0;
    4.82 +
    4.83 +    if ( *bus == 0 )
    4.84 +        /* assume integrated PCI devices in RC have valid requester-id */
    4.85 +        return 1;
    4.86 +
    4.87 +    if ( !bus2bridge[*bus].map )
    4.88 +        return 0;
    4.89  
    4.90 -static int domain_context_mapping(
    4.91 -    struct domain *domain,
    4.92 -    struct iommu *iommu,
    4.93 -    struct pci_dev *pdev)
    4.94 +    while ( bus2bridge[*bus].map )
    4.95 +    {
    4.96 +        *devfn = bus2bridge[*bus].devfn;
    4.97 +        *bus = bus2bridge[*bus].bus;
    4.98 +        if ( cnt++ >= MAX_BUSES )
    4.99 +            return 0;
   4.100 +    }
   4.101 +
   4.102 +    return 1;
   4.103 +}
   4.104 +
   4.105 +static int domain_context_mapping(struct domain *domain, u8 bus, u8 devfn)
   4.106  {
   4.107 +    struct acpi_drhd_unit *drhd;
   4.108      int ret = 0;
   4.109 -    int dev, func, sec_bus, sub_bus;
   4.110 +    u16 sec_bus, sub_bus, ob, odf;
   4.111      u32 type;
   4.112  
   4.113 -    type = pdev_type(pdev);
   4.114 +    drhd = acpi_find_matched_drhd_unit(bus, devfn);
   4.115 +    if ( !drhd )
   4.116 +        return -ENODEV;
   4.117 +
   4.118 +    type = pdev_type(bus, devfn);
   4.119      switch ( type )
   4.120      {
   4.121 -    case DEV_TYPE_PCI_BRIDGE:
   4.122 -        sec_bus = pci_conf_read8(
   4.123 -            pdev->bus, PCI_SLOT(pdev->devfn),
   4.124 -            PCI_FUNC(pdev->devfn), PCI_SECONDARY_BUS);
   4.125 +    case DEV_TYPE_PCIe_BRIDGE:
   4.126 +        break;
   4.127  
   4.128 -        if ( bus2bridge[sec_bus].bus == 0 )
   4.129 -        {
   4.130 -            bus2bridge[sec_bus].bus   =  pdev->bus;
   4.131 -            bus2bridge[sec_bus].devfn =  pdev->devfn;
   4.132 -        }
   4.133 +    case DEV_TYPE_PCI_BRIDGE:
   4.134 +        sec_bus = pci_conf_read8(bus, PCI_SLOT(devfn), PCI_FUNC(devfn),
   4.135 +                                 PCI_SECONDARY_BUS);
   4.136 +        sub_bus = pci_conf_read8(bus, PCI_SLOT(devfn), PCI_FUNC(devfn),
   4.137 +                                 PCI_SUBORDINATE_BUS);
   4.138  
   4.139 -        sub_bus = pci_conf_read8(
   4.140 -            pdev->bus, PCI_SLOT(pdev->devfn),
   4.141 -            PCI_FUNC(pdev->devfn), PCI_SUBORDINATE_BUS);
   4.142 +        for ( sub_bus &= 0xff; sec_bus <= sub_bus; sec_bus++ )
   4.143 +        {
   4.144 +            bus2bridge[sec_bus].map = 1;
   4.145 +            bus2bridge[sec_bus].bus =  bus;
   4.146 +            bus2bridge[sec_bus].devfn =  devfn;
   4.147 +        }
   4.148 +        break;
   4.149  
   4.150 -        if ( sec_bus != sub_bus )
   4.151 -            gdprintk(XENLOG_WARNING VTDPREFIX,
   4.152 -                     "context_context_mapping: nested PCI bridge not "
   4.153 -                     "supported: bdf = %x:%x:%x sec_bus = %x sub_bus = %x\n",
   4.154 -                     pdev->bus, PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn),
   4.155 -                     sec_bus, sub_bus);
   4.156 -        break;
   4.157      case DEV_TYPE_PCIe_ENDPOINT:
   4.158          gdprintk(XENLOG_INFO VTDPREFIX,
   4.159 -                 "domain_context_mapping:PCIe : bdf = %x:%x:%x\n",
   4.160 -                 pdev->bus, PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn));
   4.161 -        ret = domain_context_mapping_one(domain, iommu,
   4.162 -                                         (u8)(pdev->bus), (u8)(pdev->devfn));
   4.163 +                 "domain_context_mapping:PCIe: bdf = %x:%x.%x\n",
   4.164 +                 bus, PCI_SLOT(devfn), PCI_FUNC(devfn));
   4.165 +        ret = domain_context_mapping_one(domain, drhd->iommu, bus, devfn);
   4.166          break;
   4.167 +
   4.168      case DEV_TYPE_PCI:
   4.169          gdprintk(XENLOG_INFO VTDPREFIX,
   4.170 -                 "domain_context_mapping:PCI: bdf = %x:%x:%x\n",
   4.171 -                 pdev->bus, PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn));
   4.172 -
   4.173 -        if ( pdev->bus == 0 )
   4.174 -            ret = domain_context_mapping_one(
   4.175 -                domain, iommu, (u8)(pdev->bus), (u8)(pdev->devfn));
   4.176 -        else
   4.177 -        {
   4.178 -            if ( bus2bridge[pdev->bus].bus != 0 )
   4.179 -                gdprintk(XENLOG_WARNING VTDPREFIX,
   4.180 -                         "domain_context_mapping:bus2bridge"
   4.181 -                         "[%d].bus != 0\n", pdev->bus);
   4.182 +                 "domain_context_mapping:PCI:  bdf = %x:%x.%x\n",
   4.183 +                 bus, PCI_SLOT(devfn), PCI_FUNC(devfn));
   4.184  
   4.185 -            ret = domain_context_mapping_one(
   4.186 -                domain, iommu,
   4.187 -                (u8)(bus2bridge[pdev->bus].bus),
   4.188 -                (u8)(bus2bridge[pdev->bus].devfn));
   4.189 +        ob = bus; odf = devfn;
   4.190 +        if ( !find_pcie_endpoint(&bus, &devfn) )
   4.191 +        {
   4.192 +            gdprintk(XENLOG_WARNING VTDPREFIX, "domain_context_mapping:invalid");
   4.193 +            break;
   4.194 +        }
   4.195  
   4.196 -            /* now map everything behind the PCI bridge */
   4.197 -            for ( dev = 0; dev < 32; dev++ )
   4.198 -            {
   4.199 -                for ( func = 0; func < 8; func++ )
   4.200 -                {
   4.201 -                    ret = domain_context_mapping_one(
   4.202 -                        domain, iommu,
   4.203 -                        pdev->bus, (u8)PCI_DEVFN(dev, func));
   4.204 -                    if ( ret )
   4.205 -                        return ret;
   4.206 -                }
   4.207 -            }
   4.208 -        }
   4.209 +        if ( ob != bus || odf != devfn )
   4.210 +            gdprintk(XENLOG_INFO VTDPREFIX,
   4.211 +                     "domain_context_mapping:map:  bdf = %x:%x.%x -> %x:%x.%x\n",
   4.212 +                     ob, PCI_SLOT(odf), PCI_FUNC(odf),
   4.213 +                     bus, PCI_SLOT(devfn), PCI_FUNC(devfn));
   4.214 +        ret = domain_context_mapping_one(domain, drhd->iommu, bus, devfn);
   4.215          break;
   4.216 +
   4.217      default:
   4.218          gdprintk(XENLOG_ERR VTDPREFIX,
   4.219 -                 "domain_context_mapping:unknown type : bdf = %x:%x:%x\n",
   4.220 -                 pdev->bus, PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn));
   4.221 +                 "domain_context_mapping:unknown type : bdf = %x:%x.%x\n",
   4.222 +                 bus, PCI_SLOT(devfn), PCI_FUNC(devfn));
   4.223          ret = -EINVAL;
   4.224          break;
   4.225      }
   4.226 @@ -1266,9 +1277,7 @@ static int domain_context_mapping(
   4.227      return ret;
   4.228  }
   4.229  
   4.230 -static int domain_context_unmap_one(
   4.231 -    struct iommu *iommu,
   4.232 -    u8 bus, u8 devfn)
   4.233 +static int domain_context_unmap_one(struct iommu *iommu, u8 bus, u8 devfn)
   4.234  {
   4.235      struct context_entry *context, *context_entries;
   4.236      unsigned long flags;
   4.237 @@ -1296,61 +1305,39 @@ static int domain_context_unmap_one(
   4.238      return 0;
   4.239  }
   4.240  
   4.241 -static int domain_context_unmap(
   4.242 -    struct iommu *iommu,
   4.243 -    struct pci_dev *pdev)
   4.244 +static int domain_context_unmap(u8 bus, u8 devfn)
   4.245  {
   4.246 +    struct acpi_drhd_unit *drhd;
   4.247      int ret = 0;
   4.248 -    int dev, func, sec_bus, sub_bus;
   4.249      u32 type;
   4.250  
   4.251 -    type = pdev_type(pdev);
   4.252 +    drhd = acpi_find_matched_drhd_unit(bus, devfn);
   4.253 +    if ( !drhd )
   4.254 +        return -ENODEV;
   4.255 +
   4.256 +    type = pdev_type(bus, devfn);
   4.257      switch ( type )
   4.258      {
   4.259 +    case DEV_TYPE_PCIe_BRIDGE:
   4.260 +        break;
   4.261 +
   4.262      case DEV_TYPE_PCI_BRIDGE:
   4.263 -        sec_bus = pci_conf_read8(
   4.264 -            pdev->bus, PCI_SLOT(pdev->devfn),
   4.265 -            PCI_FUNC(pdev->devfn), PCI_SECONDARY_BUS);
   4.266 -        sub_bus = pci_conf_read8(
   4.267 -            pdev->bus, PCI_SLOT(pdev->devfn),
   4.268 -            PCI_FUNC(pdev->devfn), PCI_SUBORDINATE_BUS);
   4.269 +        ret = domain_context_unmap_one(drhd->iommu, bus, devfn);
   4.270          break;
   4.271 +
   4.272      case DEV_TYPE_PCIe_ENDPOINT:
   4.273 -        ret = domain_context_unmap_one(iommu,
   4.274 -                                       (u8)(pdev->bus), (u8)(pdev->devfn));
   4.275 +        ret = domain_context_unmap_one(drhd->iommu, bus, devfn);
   4.276          break;
   4.277 +
   4.278      case DEV_TYPE_PCI:
   4.279 -        if ( pdev->bus == 0 )
   4.280 -            ret = domain_context_unmap_one(
   4.281 -                iommu, (u8)(pdev->bus), (u8)(pdev->devfn));
   4.282 -        else
   4.283 -        {
   4.284 -            if ( bus2bridge[pdev->bus].bus != 0 )
   4.285 -                gdprintk(XENLOG_WARNING VTDPREFIX,
   4.286 -                         "domain_context_unmap:"
   4.287 -                         "bus2bridge[%d].bus != 0\n", pdev->bus);
   4.288 -
   4.289 -            ret = domain_context_unmap_one(iommu,
   4.290 -                                           (u8)(bus2bridge[pdev->bus].bus),
   4.291 -                                           (u8)(bus2bridge[pdev->bus].devfn));
   4.292 +        if ( find_pcie_endpoint(&bus, &devfn) )
   4.293 +            ret = domain_context_unmap_one(drhd->iommu, bus, devfn);
   4.294 +        break;
   4.295  
   4.296 -            /* Unmap everything behind the PCI bridge */
   4.297 -            for ( dev = 0; dev < 32; dev++ )
   4.298 -            {
   4.299 -                for ( func = 0; func < 8; func++ )
   4.300 -                {
   4.301 -                    ret = domain_context_unmap_one(
   4.302 -                        iommu, pdev->bus, (u8)PCI_DEVFN(dev, func));
   4.303 -                    if ( ret )
   4.304 -                        return ret;
   4.305 -                }
   4.306 -            }
   4.307 -        }
   4.308 -        break;
   4.309      default:
   4.310          gdprintk(XENLOG_ERR VTDPREFIX,
   4.311                   "domain_context_unmap:unknown type: bdf = %x:%x:%x\n",
   4.312 -                 pdev->bus, PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn));
   4.313 +                 bus, PCI_SLOT(devfn), PCI_FUNC(devfn));
   4.314          ret = -EINVAL;
   4.315          break;
   4.316      }
   4.317 @@ -1364,7 +1351,7 @@ void reassign_device_ownership(
   4.318      u8 bus, u8 devfn)
   4.319  {
   4.320      struct hvm_iommu *source_hd = domain_hvm_iommu(source);
   4.321 -    struct pci_dev *pdev, *pdev2;
   4.322 +    struct pci_dev *pdev;
   4.323      struct acpi_drhd_unit *drhd;
   4.324      struct iommu *iommu;
   4.325      int status;
   4.326 @@ -1378,27 +1365,28 @@ void reassign_device_ownership(
   4.327  
   4.328      return;
   4.329  
   4.330 - found:
   4.331 -    drhd = acpi_find_matched_drhd_unit(pdev);
   4.332 +found:
   4.333 +    drhd = acpi_find_matched_drhd_unit(bus, devfn);
   4.334      iommu = drhd->iommu;
   4.335 -    domain_context_unmap(iommu, pdev);
   4.336 +    domain_context_unmap(bus, devfn);
   4.337  
   4.338      /* Move pci device from the source domain to target domain. */
   4.339      list_move(&pdev->domain_list, &target->arch.pdev_list);
   4.340  
   4.341 -    for_each_pdev ( source, pdev2 )
   4.342 +    for_each_pdev ( source, pdev )
   4.343      {
   4.344 -        drhd = acpi_find_matched_drhd_unit(pdev2);
   4.345 +        drhd = acpi_find_matched_drhd_unit(pdev->bus, pdev->devfn);
   4.346          if ( drhd->iommu == iommu )
   4.347          {
   4.348              found = 1;
   4.349              break;
   4.350          }
   4.351      }
   4.352 +
   4.353      if ( !found )
   4.354          clear_bit(iommu->index, &source_hd->iommu_bitmap);
   4.355  
   4.356 -    status = domain_context_mapping(target, iommu, pdev);
   4.357 +    status = domain_context_mapping(target, bus, devfn);
   4.358      if ( status != 0 )
   4.359          gdprintk(XENLOG_ERR VTDPREFIX, "domain_context_mapping failed\n");
   4.360  }
   4.361 @@ -1436,19 +1424,13 @@ void iommu_domain_teardown(struct domain
   4.362      iommu_domid_release(d);
   4.363  }
   4.364  
   4.365 -static int domain_context_mapped(struct pci_dev *pdev)
   4.366 +static int domain_context_mapped(u8 bus, u8 devfn)
   4.367  {
   4.368      struct acpi_drhd_unit *drhd;
   4.369 -    struct iommu *iommu;
   4.370 -    int ret;
   4.371  
   4.372      for_each_drhd_unit ( drhd )
   4.373 -    {
   4.374 -        iommu = drhd->iommu;
   4.375 -        ret = device_context_mapped(iommu, pdev->bus, pdev->devfn);
   4.376 -        if ( ret )
   4.377 -            return ret;
   4.378 -    }
   4.379 +        if ( device_context_mapped(drhd->iommu, bus, devfn) )
   4.380 +            return 1;
   4.381  
   4.382      return 0;
   4.383  }
   4.384 @@ -1570,12 +1552,10 @@ int iommu_page_unmapping(struct domain *
   4.385      return 0;
   4.386  }
   4.387  
   4.388 -static int iommu_prepare_rmrr_dev(
   4.389 -    struct domain *d,
   4.390 -    struct acpi_rmrr_unit *rmrr,
   4.391 -    struct pci_dev *pdev)
   4.392 +static int iommu_prepare_rmrr_dev(struct domain *d,
   4.393 +                                  struct acpi_rmrr_unit *rmrr,
   4.394 +                                  u8 bus, u8 devfn)
   4.395  {
   4.396 -    struct acpi_drhd_unit *drhd;
   4.397      u64 size;
   4.398      int ret;
   4.399  
   4.400 @@ -1587,10 +1567,9 @@ static int iommu_prepare_rmrr_dev(
   4.401      if ( ret )
   4.402          return ret;
   4.403  
   4.404 -    if ( domain_context_mapped(pdev) == 0 )
   4.405 +    if ( domain_context_mapped(bus, devfn) == 0 )
   4.406      {
   4.407 -        drhd = acpi_find_matched_drhd_unit(pdev);
   4.408 -        ret = domain_context_mapping(d, drhd->iommu, pdev);
   4.409 +        ret = domain_context_mapping(d, bus, devfn);
   4.410          if ( !ret )
   4.411              return 0;
   4.412      }
   4.413 @@ -1601,7 +1580,6 @@ static int iommu_prepare_rmrr_dev(
   4.414  static void setup_dom0_devices(struct domain *d)
   4.415  {
   4.416      struct hvm_iommu *hd;
   4.417 -    struct acpi_drhd_unit *drhd;
   4.418      struct pci_dev *pdev;
   4.419      int bus, dev, func, ret;
   4.420      u32 l;
   4.421 @@ -1624,8 +1602,7 @@ static void setup_dom0_devices(struct do
   4.422                  pdev->devfn = PCI_DEVFN(dev, func);
   4.423                  list_add_tail(&pdev->domain_list, &d->arch.pdev_list);
   4.424  
   4.425 -                drhd = acpi_find_matched_drhd_unit(pdev);
   4.426 -                ret = domain_context_mapping(d, drhd->iommu, pdev);
   4.427 +                ret = domain_context_mapping(d, pdev->bus, pdev->devfn);
   4.428                  if ( ret != 0 )
   4.429                      gdprintk(XENLOG_ERR VTDPREFIX,
   4.430                               "domain_context_mapping failed\n");
   4.431 @@ -1701,15 +1678,16 @@ static int init_vtd_hw(void)
   4.432  static void setup_dom0_rmrr(struct domain *d)
   4.433  {
   4.434      struct acpi_rmrr_unit *rmrr;
   4.435 -    struct pci_dev *pdev;
   4.436 -    int ret;
   4.437 +    u16 bdf;
   4.438 +    int ret, i;
   4.439  
   4.440 -    for_each_rmrr_device ( rmrr, pdev )
   4.441 -        ret = iommu_prepare_rmrr_dev(d, rmrr, pdev);
   4.442 +    for_each_rmrr_device ( rmrr, bdf, i )
   4.443 +    {
   4.444 +        ret = iommu_prepare_rmrr_dev(d, rmrr, PCI_BUS(bdf), PCI_DEVFN2(bdf));
   4.445          if ( ret )
   4.446              gdprintk(XENLOG_ERR VTDPREFIX,
   4.447                       "IOMMU: mapping reserved region failed\n");
   4.448 -    end_for_each_rmrr_device ( rmrr, pdev )
   4.449 +    }
   4.450  }
   4.451  
   4.452  int intel_vtd_setup(void)
   4.453 @@ -1769,25 +1747,26 @@ int device_assigned(u8 bus, u8 devfn)
   4.454  int intel_iommu_assign_device(struct domain *d, u8 bus, u8 devfn)
   4.455  {
   4.456      struct acpi_rmrr_unit *rmrr;
   4.457 -    struct pci_dev *pdev;
   4.458 -    int ret = 0;
   4.459 +    int ret = 0, i;
   4.460 +    u16 bdf;
   4.461  
   4.462      if ( list_empty(&acpi_drhd_units) )
   4.463          return ret;
   4.464  
   4.465      reassign_device_ownership(dom0, d, bus, devfn);
   4.466  
   4.467 -    /* Setup rmrr identify mapping */
   4.468 -    for_each_rmrr_device( rmrr, pdev )
   4.469 -        if ( pdev->bus == bus && pdev->devfn == devfn )
   4.470 +    /* Setup rmrr identity mapping */
   4.471 +    for_each_rmrr_device( rmrr, bdf, i )
   4.472 +    {
   4.473 +        if ( PCI_BUS(bdf) == bus && PCI_DEVFN2(bdf) == devfn )
   4.474          {
   4.475              /* FIXME: Because USB RMRR conflicts with guest bios region,
   4.476               * ignore USB RMRR temporarily.
   4.477               */
   4.478 -            if ( is_usb_device(pdev) )
   4.479 +            if ( is_usb_device(bus, devfn) )
   4.480                  return 0;
   4.481  
   4.482 -            ret = iommu_prepare_rmrr_dev(d, rmrr, pdev);
   4.483 +            ret = iommu_prepare_rmrr_dev(d, rmrr, bus, devfn);
   4.484              if ( ret )
   4.485              {
   4.486                  gdprintk(XENLOG_ERR VTDPREFIX,
   4.487 @@ -1795,11 +1774,19 @@ int intel_iommu_assign_device(struct dom
   4.488                  return ret;
   4.489              }
   4.490          }
   4.491 -    end_for_each_rmrr_device(rmrr, pdev)
   4.492 +    }
   4.493  
   4.494      return ret;
   4.495  }
   4.496  
   4.497 +static int intel_iommu_group_id(u8 bus, u8 devfn)
   4.498 +{
   4.499 +    if ( !bus2bridge[bus].map || find_pcie_endpoint(&bus, &devfn) )
   4.500 +        return PCI_BDF2(bus, devfn);
   4.501 +    else
   4.502 +        return -1;
   4.503 +}
   4.504 +
   4.505  u8 iommu_state[MAX_IOMMU_REGS * MAX_IOMMUS];
   4.506  int iommu_suspend(void)
   4.507  {
   4.508 @@ -1881,7 +1868,7 @@ struct iommu_ops intel_iommu_ops = {
   4.509      .map_page = intel_iommu_map_page,
   4.510      .unmap_page = intel_iommu_unmap_page,
   4.511      .reassign_device = reassign_device_ownership,
   4.512 -    .get_device_group_id = NULL,
   4.513 +    .get_device_group_id = intel_iommu_group_id,
   4.514  };
   4.515  
   4.516  /*
     5.1 --- a/xen/drivers/passthrough/vtd/utils.c	Fri Jul 04 17:51:16 2008 +0100
     5.2 +++ b/xen/drivers/passthrough/vtd/utils.c	Fri Jul 04 17:51:42 2008 +0100
     5.3 @@ -32,12 +32,10 @@
     5.4  #define SEABURG 0x4000
     5.5  #define C_STEP  2
     5.6  
     5.7 -int is_usb_device(struct pci_dev *pdev)
     5.8 +int is_usb_device(u8 bus, u8 devfn)
     5.9  {
    5.10 -    u8 bus = pdev->bus;
    5.11 -    u8 dev = PCI_SLOT(pdev->devfn);
    5.12 -    u8 func = PCI_FUNC(pdev->devfn);
    5.13 -    u16 class = pci_conf_read16(bus, dev, func, PCI_CLASS_DEVICE);
    5.14 +    u16 class = pci_conf_read16(bus, PCI_SLOT(devfn), PCI_FUNC(devfn),
    5.15 +                                PCI_CLASS_DEVICE);
    5.16      return (class == 0xc03);
    5.17  }
    5.18  
     6.1 --- a/xen/include/xen/pci.h	Fri Jul 04 17:51:16 2008 +0100
     6.2 +++ b/xen/include/xen/pci.h	Fri Jul 04 17:51:42 2008 +0100
     6.3 @@ -20,9 +20,13 @@
     6.4   *  7:3 = slot
     6.5   *  2:0 = function
     6.6   */
     6.7 -#define PCI_DEVFN(slot,func)  (((slot & 0x1f) << 3) | (func & 0x07))
     6.8 -#define PCI_SLOT(devfn)       (((devfn) >> 3) & 0x1f)
     6.9 -#define PCI_FUNC(devfn)       ((devfn) & 0x07)
    6.10 +#define PCI_BUS(bdf)    (((bdf) >> 8) & 0xff)
    6.11 +#define PCI_SLOT(bdf)   (((bdf) >> 3) & 0x1f)
    6.12 +#define PCI_FUNC(bdf)   ((bdf) & 0x07)
    6.13 +#define PCI_DEVFN(d,f)  (((d & 0x1f) << 3) | (f & 0x07))
    6.14 +#define PCI_DEVFN2(bdf) ((bdf) & 0xff)
    6.15 +#define PCI_BDF(b,d,f)  (((b * 0xff) << 8) | PCI_DEVFN(d,f))
    6.16 +#define PCI_BDF2(b,df)  (((b & 0xff) << 8) | (df & 0xff))
    6.17  
    6.18  struct pci_dev {
    6.19      struct list_head domain_list;
    6.20 @@ -32,6 +36,10 @@ struct pci_dev {
    6.21      struct list_head msi_list;
    6.22  };
    6.23  
    6.24 +#define for_each_pdev(domain, pdev) \
    6.25 +    list_for_each_entry(pdev, &(domain->arch.pdev_list), domain_list)
    6.26 +
    6.27 +
    6.28  uint8_t pci_conf_read8(
    6.29      unsigned int bus, unsigned int dev, unsigned int func, unsigned int reg);
    6.30  uint16_t pci_conf_read16(
    6.31 @@ -50,9 +58,4 @@ void pci_conf_write32(
    6.32  int pci_find_cap_offset(u8 bus, u8 dev, u8 func, u8 cap);
    6.33  int pci_find_next_cap(u8 bus, unsigned int devfn, u8 pos, int cap);
    6.34  
    6.35 -
    6.36 -#define for_each_pdev(domain, pdev) \
    6.37 -    list_for_each_entry(pdev, &(domain->arch.pdev_list), domain_list)
    6.38 -
    6.39 -
    6.40  #endif /* __XEN_PCI_H__ */