Signed-off-by: Jan Beulich <jbeulich@xxxxxxxx>
--- 2011-09-20.orig/xen/drivers/passthrough/vtd/dmar.c 2011-08-16
08:15:46.000000000 +0200
+++ 2011-09-20/xen/drivers/passthrough/vtd/dmar.c 2011-08-25
15:06:43.000000000 +0200
@@ -188,6 +188,9 @@ struct acpi_drhd_unit * acpi_find_matche
list_for_each_entry ( drhd, &acpi_drhd_units, list )
{
+ if ( drhd->segment != pdev->seg )
+ continue;
+
for (i = 0; i < drhd->scope.devices_cnt; i++)
if ( drhd->scope.devices[i] == PCI_BDF2(bus, devfn) )
return drhd;
@@ -201,13 +204,16 @@ struct acpi_drhd_unit * acpi_find_matche
return include_all;
}
-struct acpi_atsr_unit * acpi_find_matched_atsr_unit(u8 bus, u8 devfn)
+struct acpi_atsr_unit * acpi_find_matched_atsr_unit(u16 seg, u8 bus, u8 devfn)
{
struct acpi_atsr_unit *atsr;
struct acpi_atsr_unit *all_ports = NULL;
list_for_each_entry ( atsr, &acpi_atsr_units, list )
{
+ if ( atsr->segment != seg )
+ continue;
+
if ( test_bit(bus, atsr->scope.buses) )
return atsr;
@@ -269,8 +275,8 @@ static int scope_device_count(void *star
}
-static int __init acpi_parse_dev_scope(void *start, void *end,
- void *acpi_entry, int type)
+static int __init acpi_parse_dev_scope(
+ void *start, void *end, void *acpi_entry, int type, u16 seg)
{
struct dmar_scope *scope = acpi_entry;
struct acpi_ioapic_unit *acpi_ioapic_unit;
@@ -314,8 +320,8 @@ static int __init acpi_parse_dev_scope(v
bus, path->dev, path->fn, PCI_SUBORDINATE_BUS);
if ( iommu_verbose )
dprintk(VTDPREFIX,
- " bridge: %x:%x.%x start = %x sec = %x sub = %x\n",
- bus, path->dev, path->fn,
+ " bridge: %04x:%02x:%02x.%u start=%x sec=%x sub=%x\n",
+ seg, bus, path->dev, path->fn,
acpi_scope->start_bus, sec_bus, sub_bus);
dmar_scope_add_buses(scope, sec_bus, sub_bus);
@@ -323,20 +329,21 @@ static int __init acpi_parse_dev_scope(v
case ACPI_DEV_MSI_HPET:
if ( iommu_verbose )
- dprintk(VTDPREFIX, " MSI HPET: %x:%x.%x\n",
- bus, path->dev, path->fn);
+ dprintk(VTDPREFIX, " MSI HPET: %04x:%02x:%02x.%u\n",
+ seg, bus, path->dev, path->fn);
break;
case ACPI_DEV_ENDPOINT:
if ( iommu_verbose )
- dprintk(VTDPREFIX, " endpoint: %x:%x.%x\n",
- bus, path->dev, path->fn);
+ dprintk(VTDPREFIX, " endpoint: %04x:%02x:%02x.%u\n",
+ seg, bus, path->dev, path->fn);
if ( type == DMAR_TYPE )
{
struct acpi_drhd_unit *drhd = acpi_entry;
- if ( (bus == 0) && (path->dev == 2) && (path->fn == 0) )
+ if ( (seg == 0) && (bus == 0) && (path->dev == 2) &&
+ (path->fn == 0) )
igd_drhd_address = drhd->address;
}
@@ -344,8 +351,8 @@ static int __init acpi_parse_dev_scope(v
case ACPI_DEV_IOAPIC:
if ( iommu_verbose )
- dprintk(VTDPREFIX, " IOAPIC: %x:%x.%x\n",
- bus, path->dev, path->fn);
+ dprintk(VTDPREFIX, " IOAPIC: %04x:%02x:%02x.%u\n",
+ seg, bus, path->dev, path->fn);
if ( type == DMAR_TYPE )
{
@@ -398,6 +405,7 @@ acpi_parse_one_drhd(struct acpi_dmar_ent
memset(dmaru, 0, sizeof(struct acpi_drhd_unit));
dmaru->address = drhd->address;
+ dmaru->segment = drhd->segment;
dmaru->include_all = drhd->flags & 1; /* BIT0: INCLUDE_ALL */
INIT_LIST_HEAD(&dmaru->ioapic_list);
if ( iommu_verbose )
@@ -411,7 +419,7 @@ acpi_parse_one_drhd(struct acpi_dmar_ent
dev_scope_start = (void *)(drhd + 1);
dev_scope_end = ((void *)drhd) + header->length;
ret = acpi_parse_dev_scope(dev_scope_start, dev_scope_end,
- dmaru, DMAR_TYPE);
+ dmaru, DMAR_TYPE, drhd->segment);
if ( dmaru->include_all )
{
@@ -528,11 +536,12 @@ acpi_parse_one_rmrr(struct acpi_dmar_ent
rmrru->base_address = base_addr;
rmrru->end_address = end_addr;
+ rmrru->segment = rmrr->segment;
dev_scope_start = (void *)(rmrr + 1);
dev_scope_end = ((void *)rmrr) + header->length;
ret = acpi_parse_dev_scope(dev_scope_start, dev_scope_end,
- rmrru, RMRR_TYPE);
+ rmrru, RMRR_TYPE, rmrr->segment);
if ( ret || (rmrru->scope.devices_cnt == 0) )
xfree(rmrru);
@@ -609,6 +618,7 @@ acpi_parse_one_atsr(struct acpi_dmar_ent
return -ENOMEM;
memset(atsru, 0, sizeof(struct acpi_atsr_unit));
+ atsru->segment = atsr->segment;
atsru->all_ports = atsr->flags & 1; /* BIT0: ALL_PORTS */
if ( iommu_verbose )
dprintk(VTDPREFIX,
@@ -618,7 +628,7 @@ acpi_parse_one_atsr(struct acpi_dmar_ent
dev_scope_start = (void *)(atsr + 1);
dev_scope_end = ((void *)atsr) + header->length;
ret = acpi_parse_dev_scope(dev_scope_start, dev_scope_end,
- atsru, ATSR_TYPE);
+ atsru, ATSR_TYPE, atsr->segment);
}
else
{
--- 2011-09-20.orig/xen/drivers/passthrough/vtd/dmar.h 2011-06-20
08:41:50.000000000 +0200
+++ 2011-09-20/xen/drivers/passthrough/vtd/dmar.h 2011-08-25
15:06:43.000000000 +0200
@@ -49,6 +49,7 @@ struct acpi_drhd_unit {
struct dmar_scope scope; /* must be first member of struct */
struct list_head list;
u64 address; /* register base address of the unit */
+ u16 segment;
u8 include_all:1;
struct iommu *iommu;
struct list_head ioapic_list;
@@ -59,12 +60,14 @@ struct acpi_rmrr_unit {
struct list_head list;
u64 base_address;
u64 end_address;
+ u16 segment;
u8 allow_all:1;
};
struct acpi_atsr_unit {
struct dmar_scope scope; /* must be first member of struct */
struct list_head list;
+ u16 segment;
u8 all_ports:1;
};
@@ -84,7 +87,7 @@ struct acpi_rhsa_unit {
idx < rmrr->scope.devices_cnt; idx++)
struct acpi_drhd_unit * acpi_find_matched_drhd_unit(struct pci_dev *pdev);
-struct acpi_atsr_unit * acpi_find_matched_atsr_unit(u8 bus, u8 devfn);
+struct acpi_atsr_unit * acpi_find_matched_atsr_unit(u16 seg, u8 bus, u8 devfn);
#define DMAR_TYPE 1
#define RMRR_TYPE 2
@@ -114,7 +117,7 @@ void *map_to_nocache_virt(int nr_iommus,
int vtd_hw_check(void);
void disable_pmr(struct iommu *iommu);
-int is_usb_device(u8 bus, u8 devfn);
+int is_usb_device(u16 seg, u8 bus, u8 devfn);
int is_igd_drhd(struct acpi_drhd_unit *drhd);
#endif /* _DMAR_H_ */
--- 2011-09-20.orig/xen/drivers/passthrough/vtd/iommu.c 2011-09-20
16:04:11.000000000 +0200
+++ 2011-09-20/xen/drivers/passthrough/vtd/iommu.c 2011-09-20
16:06:24.000000000 +0200
@@ -835,16 +835,17 @@ static int iommu_page_fault_do_one(struc
{
const char *reason;
int fault_type;
+ u16 seg = iommu->intel->drhd->segment;
reason = iommu_get_fault_reason(fault_reason, &fault_type);
if ( fault_type == DMA_REMAP )
{
INTEL_IOMMU_DEBUG(
- "DMAR:[%s] Request device [%02x:%02x.%d] "
+ "DMAR:[%s] Request device [%04x:%02x:%02x.%u] "
"fault addr %"PRIx64", iommu reg = %p\n"
"DMAR:[fault reason %02xh] %s\n",
(type ? "DMA Read" : "DMA Write"),
- (source_id >> 8), PCI_SLOT(source_id & 0xFF),
+ seg, (source_id >> 8), PCI_SLOT(source_id & 0xFF),
PCI_FUNC(source_id & 0xFF), addr, iommu->reg,
fault_reason, reason);
#ifndef __i386__ /* map_domain_page() cannot be used in this context */
@@ -855,10 +856,10 @@ static int iommu_page_fault_do_one(struc
}
else
INTEL_IOMMU_DEBUG(
- "INTR-REMAP: Request device [%02x:%02x.%d] "
+ "INTR-REMAP: Request device [%04x:%02x:%02x.%u] "
"fault index %"PRIx64", iommu reg = %p\n"
"INTR-REMAP:[fault reason %02xh] %s\n",
- (source_id >> 8), PCI_SLOT(source_id & 0xFF),
+ seg, (source_id >> 8), PCI_SLOT(source_id & 0xFF),
PCI_FUNC(source_id & 0xFF), addr >> 48, iommu->reg,
fault_reason, reason);
return 0;
@@ -1258,6 +1259,7 @@ int domain_context_mapping_one(
struct hvm_iommu *hd = domain_hvm_iommu(domain);
struct context_entry *context, *context_entries;
u64 maddr, pgd_maddr;
+ u16 seg = iommu->intel->drhd->segment;
int agaw;
ASSERT(spin_is_locked(&pcidevs_lock));
@@ -1273,7 +1275,7 @@ int domain_context_mapping_one(
/* First try to get domain ownership from device structure. If that's
* not available, try to read it from the context itself. */
- pdev = pci_get_pdev(0, bus, devfn);
+ pdev = pci_get_pdev(seg, bus, devfn);
if ( pdev )
{
if ( pdev->domain != domain )
@@ -1385,18 +1387,20 @@ int domain_context_mapping_one(
unmap_vtd_domain_page(context_entries);
- me_wifi_quirk(domain, bus, devfn, MAP_ME_PHANTOM_FUNC);
+ if ( !seg )
+ me_wifi_quirk(domain, bus, devfn, MAP_ME_PHANTOM_FUNC);
return 0;
}
-static int domain_context_mapping(struct domain *domain, u8 bus, u8 devfn)
+static int domain_context_mapping(
+ struct domain *domain, u16 seg, u8 bus, u8 devfn)
{
struct acpi_drhd_unit *drhd;
int ret = 0;
u32 type;
u8 secbus;
- struct pci_dev *pdev = pci_get_pdev(0, bus, devfn);
+ struct pci_dev *pdev = pci_get_pdev(seg, bus, devfn);
drhd = acpi_find_matched_drhd_unit(pdev);
if ( !drhd )
@@ -1414,18 +1418,20 @@ static int domain_context_mapping(struct
case DEV_TYPE_PCIe_ENDPOINT:
if ( iommu_verbose )
- dprintk(VTDPREFIX, "d%d:PCIe: map bdf = %x:%x.%x\n",
- domain->domain_id, bus, PCI_SLOT(devfn), PCI_FUNC(devfn));
+ dprintk(VTDPREFIX, "d%d:PCIe: map %04x:%02x:%02x.%u\n",
+ domain->domain_id, seg, bus,
+ PCI_SLOT(devfn), PCI_FUNC(devfn));
ret = domain_context_mapping_one(domain, drhd->iommu, bus, devfn);
- if ( !ret && ats_device(0, bus, devfn) )
- enable_ats_device(0, bus, devfn);
+ if ( !ret && ats_device(seg, bus, devfn) )
+ enable_ats_device(seg, bus, devfn);
break;
case DEV_TYPE_PCI:
if ( iommu_verbose )
- dprintk(VTDPREFIX, "d%d:PCI: map bdf = %x:%x.%x\n",
- domain->domain_id, bus, PCI_SLOT(devfn), PCI_FUNC(devfn));
+ dprintk(VTDPREFIX, "d%d:PCI: map %04x:%02x:%02x.%u\n",
+ domain->domain_id, seg, bus,
+ PCI_SLOT(devfn), PCI_FUNC(devfn));
ret = domain_context_mapping_one(domain, drhd->iommu, bus, devfn);
if ( ret )
@@ -1448,9 +1454,9 @@ static int domain_context_mapping(struct
break;
default:
- dprintk(XENLOG_ERR VTDPREFIX, "d%d:unknown(%u): bdf = %x:%x.%x\n",
+ dprintk(XENLOG_ERR VTDPREFIX, "d%d:unknown(%u): %04x:%02x:%02x.%u\n",
domain->domain_id, type,
- bus, PCI_SLOT(devfn), PCI_FUNC(devfn));
+ seg, bus, PCI_SLOT(devfn), PCI_FUNC(devfn));
ret = -EINVAL;
break;
}
@@ -1509,19 +1515,21 @@ int domain_context_unmap_one(
spin_unlock(&iommu->lock);
unmap_vtd_domain_page(context_entries);
- me_wifi_quirk(domain, bus, devfn, UNMAP_ME_PHANTOM_FUNC);
+ if ( !iommu->intel->drhd->segment )
+ me_wifi_quirk(domain, bus, devfn, UNMAP_ME_PHANTOM_FUNC);
return 0;
}
-static int domain_context_unmap(struct domain *domain, u8 bus, u8 devfn)
+static int domain_context_unmap(
+ struct domain *domain, u16 seg, u8 bus, u8 devfn)
{
struct acpi_drhd_unit *drhd;
struct iommu *iommu;
int ret = 0;
u32 type;
u8 tmp_bus, tmp_devfn, secbus;
- struct pci_dev *pdev = pci_get_pdev(0, bus, devfn);
+ struct pci_dev *pdev = pci_get_pdev(seg, bus, devfn);
int found = 0;
BUG_ON(!pdev);
@@ -1541,18 +1549,19 @@ static int domain_context_unmap(struct d
case DEV_TYPE_PCIe_ENDPOINT:
if ( iommu_verbose )
- dprintk(VTDPREFIX, "d%d:PCIe: unmap bdf = %x:%x.%x\n",
- domain->domain_id, bus, PCI_SLOT(devfn), PCI_FUNC(devfn));
+ dprintk(VTDPREFIX, "d%d:PCIe: unmap %04x:%02x:%02x.%u\n",
+ domain->domain_id, seg, bus,
+ PCI_SLOT(devfn), PCI_FUNC(devfn));
ret = domain_context_unmap_one(domain, iommu, bus, devfn);
- if ( !ret && ats_device(0, bus, devfn) )
- disable_ats_device(0, bus, devfn);
+ if ( !ret && ats_device(seg, bus, devfn) )
+ disable_ats_device(seg, bus, devfn);
break;
case DEV_TYPE_PCI:
if ( iommu_verbose )
- dprintk(VTDPREFIX, "d%d:PCI: unmap bdf = %x:%x.%x\n",
- domain->domain_id, bus, PCI_SLOT(devfn), PCI_FUNC(devfn));
+ dprintk(VTDPREFIX, "d%d:PCI: unmap %04x:%02x:%02x.%u\n",
+ domain->domain_id, seg, bus, PCI_SLOT(devfn),
PCI_FUNC(devfn));
ret = domain_context_unmap_one(domain, iommu, bus, devfn);
if ( ret )
break;
@@ -1577,9 +1586,9 @@ static int domain_context_unmap(struct d
break;
default:
- dprintk(XENLOG_ERR VTDPREFIX, "d%d:unknown(%u): bdf = %x:%x.%x\n",
+ dprintk(XENLOG_ERR VTDPREFIX, "d%d:unknown(%u): %04x:%02x:%02x.%u\n",
domain->domain_id, type,
- bus, PCI_SLOT(devfn), PCI_FUNC(devfn));
+ seg, bus, PCI_SLOT(devfn), PCI_FUNC(devfn));
ret = -EINVAL;
goto out;
}
@@ -1590,7 +1599,7 @@ static int domain_context_unmap(struct d
*/
for_each_pdev ( domain, pdev )
{
- if ( pdev->bus == bus && pdev->devfn == devfn )
+ if ( pdev->seg == seg && pdev->bus == bus && pdev->devfn == devfn )
continue;
drhd = acpi_find_matched_drhd_unit(pdev);
@@ -1645,11 +1654,11 @@ static int reassign_device_ownership(
if ( (target != dom0) && !iommu_intremap )
untrusted_msi = 1;
- ret = domain_context_unmap(source, bus, devfn);
+ ret = domain_context_unmap(source, seg, bus, devfn);
if ( ret )
return ret;
- ret = domain_context_mapping(target, bus, devfn);
+ ret = domain_context_mapping(target, seg, bus, devfn);
if ( ret )
return ret;
@@ -1884,7 +1893,8 @@ static int intel_iommu_add_device(struct
if ( !pdev->domain )
return -EINVAL;
- ret = domain_context_mapping(pdev->domain, pdev->bus, pdev->devfn);
+ ret = domain_context_mapping(pdev->domain, pdev->seg, pdev->bus,
+ pdev->devfn);
if ( ret )
{
dprintk(XENLOG_ERR VTDPREFIX, "d%d: context mapping failed\n",
@@ -1894,7 +1904,9 @@ static int intel_iommu_add_device(struct
for_each_rmrr_device ( rmrr, bdf, i )
{
- if ( PCI_BUS(bdf) == pdev->bus && PCI_DEVFN2(bdf) == pdev->devfn )
+ if ( rmrr->segment == pdev->seg &&
+ PCI_BUS(bdf) == pdev->bus &&
+ PCI_DEVFN2(bdf) == pdev->devfn )
{
ret = rmrr_identity_mapping(pdev->domain, rmrr);
if ( ret )
@@ -1922,13 +1934,15 @@ static int intel_iommu_remove_device(str
{
for_each_rmrr_device ( rmrr, bdf, i )
{
- if ( PCI_BUS(bdf) == pdev->bus &&
+ if ( rmrr->segment == pdev->seg &&
+ PCI_BUS(bdf) == pdev->bus &&
PCI_DEVFN2(bdf) == pdev->devfn )
return 0;
}
}
- return domain_context_unmap(pdev->domain, pdev->bus, pdev->devfn);
+ return domain_context_unmap(pdev->domain, pdev->seg, pdev->bus,
+ pdev->devfn);
}
static void __init setup_dom0_devices(struct domain *d)
@@ -1947,7 +1961,7 @@ static void __init setup_dom0_devices(st
pdev->domain = d;
list_add(&pdev->domain_list, &d->arch.pdev_list);
- domain_context_mapping(d, pdev->bus, pdev->devfn);
+ domain_context_mapping(d, pdev->seg, pdev->bus, pdev->devfn);
pci_enable_acs(pdev);
pci_vtd_quirk(pdev);
}
@@ -2196,7 +2210,7 @@ static int intel_iommu_assign_device(
/* FIXME: Because USB RMRR conflicts with guest bios region,
* ignore USB RMRR temporarily.
*/
- if ( is_usb_device(bus, devfn) )
+ if ( is_usb_device(seg, bus, devfn) )
{
ret = 0;
goto done;
@@ -2205,7 +2219,9 @@ static int intel_iommu_assign_device(
/* Setup rmrr identity mapping */
for_each_rmrr_device( rmrr, bdf, i )
{
- if ( PCI_BUS(bdf) == bus && PCI_DEVFN2(bdf) == devfn )
+ if ( rmrr->segment == seg &&
+ PCI_BUS(bdf) == bus &&
+ PCI_DEVFN2(bdf) == devfn )
{
ret = rmrr_identity_mapping(d, rmrr);
if ( ret )
--- 2011-09-20.orig/xen/drivers/passthrough/vtd/utils.c 2011-08-19
17:08:35.000000000 +0200
+++ 2011-09-20/xen/drivers/passthrough/vtd/utils.c 2011-08-25
15:06:43.000000000 +0200
@@ -32,7 +32,7 @@
#include <asm/io_apic.h>
#endif
-int is_usb_device(u8 bus, u8 devfn)
+int is_usb_device(u16 seg, u8 bus, u8 devfn)
{
u16 class = pci_conf_read16(bus, PCI_SLOT(devfn), PCI_FUNC(devfn),
PCI_CLASS_DEVICE);
@@ -106,8 +106,9 @@ void print_vtd_entries(struct iommu *iom
u64 *l, val;
u32 l_index, level;
- printk("print_vtd_entries: iommu = %p bdf = %x:%x.%x gmfn = %"PRIx64"\n",
- iommu, bus, PCI_SLOT(devfn), PCI_FUNC(devfn), gmfn);
+ printk("print_vtd_entries: iommu %p dev %04x:%02x:%02x.%u gmfn
%"PRIx64"\n",
+ iommu, iommu->intel->drhd->segment, bus,
+ PCI_SLOT(devfn), PCI_FUNC(devfn), gmfn);
if ( iommu->root_maddr == 0 )
{
--- 2011-09-20.orig/xen/drivers/passthrough/vtd/x86/ats.c 2011-08-25
15:06:35.000000000 +0200
+++ 2011-09-20/xen/drivers/passthrough/vtd/x86/ats.c 2011-08-25
15:06:43.000000000 +0200
@@ -104,7 +104,7 @@ int ats_device(int seg, int bus, int dev
!ecap_dev_iotlb(drhd->iommu->ecap) )
return 0;
- if ( !acpi_find_matched_atsr_unit(bus, devfn) )
+ if ( !acpi_find_matched_atsr_unit(seg, bus, devfn) )
return 0;
ats_drhd = find_ats_dev_drhd(drhd->iommu);
pci-multi-seg-vtd.patch
Description: Text document
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel
|