[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] Xen: use proper device ID to search VT-d unit for ARI and SR-IOV device
# HG changeset patch # User Keir Fraser <keir.fraser@xxxxxxxxxx> # Date 1237458011 0 # Node ID f02a528d2e568b0a8899981677a013da749b7a28 # Parent e2ada9d65bcafca6cbea903b0a89ae8e60ee5cec Xen: use proper device ID to search VT-d unit for ARI and SR-IOV device PCIe Alternative Routing-ID Interpretation (ARI) ECN defines the Extended Function -- a function whose function number is greater than 7 within an ARI Device. Intel VT-d spec 1.2 section 8.3.2 specifies that the Extended Function is under the scope of the same remapping unit as the traditional function. The hypervisor needs to know if a function is Extended Function so it can find proper DMAR for it. And section 8.3.3 specifies that the SR-IOV Virtual Function is under the scope of the same remapping unit as the Physical Function. The hypervisor also needs to know if a function is the Virtual Function and which Physical Function it's associated with for same reason. Signed-off-by: Yu Zhao <yu.zhao@xxxxxxxxx> --- xen/arch/ia64/xen/hypercall.c | 22 +++++++++++++++++ xen/arch/x86/physdev.c | 26 ++++++++++++++++++++ xen/drivers/passthrough/pci.c | 41 +++++++++++++++++++++++++++++++++ xen/drivers/passthrough/vtd/dmar.c | 16 +++++++++++- xen/drivers/passthrough/vtd/dmar.h | 2 - xen/drivers/passthrough/vtd/intremap.c | 4 +-- xen/drivers/passthrough/vtd/iommu.c | 18 +++++++++----- xen/include/public/physdev.h | 16 ++++++++++++ xen/include/xen/pci.h | 11 ++++++++ 9 files changed, 145 insertions(+), 11 deletions(-) diff -r e2ada9d65bca -r f02a528d2e56 xen/arch/ia64/xen/hypercall.c --- a/xen/arch/ia64/xen/hypercall.c Thu Mar 19 10:10:59 2009 +0000 +++ b/xen/arch/ia64/xen/hypercall.c Thu Mar 19 10:20:11 2009 +0000 @@ -674,6 +674,28 @@ long do_physdev_op(int cmd, XEN_GUEST_HA break; } + case PHYSDEVOP_manage_pci_add_ext: { + struct physdev_manage_pci_ext manage_pci_ext; + struct pci_dev_info pdev_info; + + ret = -EPERM; + if ( !IS_PRIV(current->domain) ) + break; + + ret = -EFAULT; + if ( copy_from_guest(&manage_pci_ext, arg, 1) != 0 ) + break; + + pdev_info.is_extfn = manage_pci_ext.is_extfn; + pdev_info.is_virtfn = manage_pci_ext.is_virtfn; + pdev_info.physfn.bus = manage_pci_ext.physfn.bus; + pdev_info.physfn.devfn = manage_pci_ext.physfn.devfn; + ret = pci_add_device_ext(manage_pci_ext.bus, + manage_pci_ext.devfn, + &pdev_info); + break; + } + default: ret = -ENOSYS; printk("not implemented do_physdev_op: %d\n", cmd); diff -r e2ada9d65bca -r f02a528d2e56 xen/arch/x86/physdev.c --- a/xen/arch/x86/physdev.c Thu Mar 19 10:10:59 2009 +0000 +++ b/xen/arch/x86/physdev.c Thu Mar 19 10:20:11 2009 +0000 @@ -421,6 +421,32 @@ ret_t do_physdev_op(int cmd, XEN_GUEST_H break; } + case PHYSDEVOP_manage_pci_add_ext: { + struct physdev_manage_pci_ext manage_pci_ext; + struct pci_dev_info pdev_info; + + ret = -EPERM; + if ( !IS_PRIV(current->domain) ) + break; + + ret = -EFAULT; + if ( copy_from_guest(&manage_pci_ext, arg, 1) != 0 ) + break; + + ret = -EINVAL; + if ( (manage_pci_ext.is_extfn > 1) || (manage_pci_ext.is_virtfn > 1) ) + break; + + pdev_info.is_extfn = manage_pci_ext.is_extfn; + pdev_info.is_virtfn = manage_pci_ext.is_virtfn; + pdev_info.physfn.bus = manage_pci_ext.physfn.bus; + pdev_info.physfn.devfn = manage_pci_ext.physfn.devfn; + ret = pci_add_device_ext(manage_pci_ext.bus, + manage_pci_ext.devfn, + &pdev_info); + break; + } + case PHYSDEVOP_restore_msi: { struct physdev_restore_msi restore_msi; struct pci_dev *pdev; diff -r e2ada9d65bca -r f02a528d2e56 xen/drivers/passthrough/pci.c --- a/xen/drivers/passthrough/pci.c Thu Mar 19 10:10:59 2009 +0000 +++ b/xen/drivers/passthrough/pci.c Thu Mar 19 10:20:11 2009 +0000 @@ -143,6 +143,47 @@ int pci_remove_device(u8 bus, u8 devfn) return ret; } +int pci_add_device_ext(u8 bus, u8 devfn, struct pci_dev_info *info) +{ + int ret; + char *pdev_type; + struct pci_dev *pdev; + + if (info->is_extfn) + pdev_type = "Extended Function"; + else if (info->is_virtfn) + pdev_type = "Virtual Function"; + else + return -EINVAL;; + + + ret = -ENOMEM; + spin_lock(&pcidevs_lock); + pdev = alloc_pdev(bus, devfn); + if ( !pdev ) + goto out; + + pdev->info = *info; + + ret = 0; + if ( !pdev->domain ) + { + pdev->domain = dom0; + ret = iommu_add_device(pdev); + if ( ret ) + goto out; + + list_add(&pdev->domain_list, &dom0->arch.pdev_list); + } + +out: + spin_unlock(&pcidevs_lock); + printk(XENLOG_DEBUG "PCI add %s %02x:%02x.%x\n", pdev_type, + bus, PCI_SLOT(devfn), PCI_FUNC(devfn)); + + return ret; +} + static void pci_clean_dpci_irqs(struct domain *d) { struct hvm_irq_dpci *hvm_irq_dpci = NULL; diff -r e2ada9d65bca -r f02a528d2e56 xen/drivers/passthrough/vtd/dmar.c --- a/xen/drivers/passthrough/vtd/dmar.c Thu Mar 19 10:10:59 2009 +0000 +++ b/xen/drivers/passthrough/vtd/dmar.c Thu Mar 19 10:20:11 2009 +0000 @@ -152,11 +152,23 @@ static int __init acpi_register_atsr_uni return 0; } -struct acpi_drhd_unit * acpi_find_matched_drhd_unit(u8 bus, u8 devfn) -{ +struct acpi_drhd_unit * acpi_find_matched_drhd_unit(struct pci_dev *pdev) +{ + u8 bus, devfn; struct acpi_drhd_unit *drhd; struct acpi_drhd_unit *found = NULL, *include_all = NULL; int i; + + if (pdev->info.is_extfn) { + bus = pdev->bus; + devfn = 0; + } else if (pdev->info.is_virtfn) { + bus = pdev->info.physfn.bus; + devfn = PCI_SLOT(pdev->info.physfn.devfn) ? 0 : pdev->info.physfn.devfn; + } else { + bus = pdev->bus; + devfn = pdev->devfn; + } list_for_each_entry ( drhd, &acpi_drhd_units, list ) { diff -r e2ada9d65bca -r f02a528d2e56 xen/drivers/passthrough/vtd/dmar.h --- a/xen/drivers/passthrough/vtd/dmar.h Thu Mar 19 10:10:59 2009 +0000 +++ b/xen/drivers/passthrough/vtd/dmar.h Thu Mar 19 10:20:11 2009 +0000 @@ -79,7 +79,7 @@ struct acpi_atsr_unit { for (idx = 0; (bdf = rmrr->scope.devices[idx]) && \ idx < rmrr->scope.devices_cnt; idx++) -struct acpi_drhd_unit * acpi_find_matched_drhd_unit(u8 bus, u8 devfn); +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); void dmar_scope_add_buses(struct dmar_scope *scope, u16 sec, u16 sub); void dmar_scope_remove_buses(struct dmar_scope *scope, u16 sec, u16 sub); diff -r e2ada9d65bca -r f02a528d2e56 xen/drivers/passthrough/vtd/intremap.c --- a/xen/drivers/passthrough/vtd/intremap.c Thu Mar 19 10:10:59 2009 +0000 +++ b/xen/drivers/passthrough/vtd/intremap.c Thu Mar 19 10:20:11 2009 +0000 @@ -450,7 +450,7 @@ void msi_msg_read_remap_rte( struct iommu *iommu = NULL; struct ir_ctrl *ir_ctrl; - drhd = acpi_find_matched_drhd_unit(pdev->bus, pdev->devfn); + drhd = acpi_find_matched_drhd_unit(pdev); iommu = drhd->iommu; ir_ctrl = iommu_ir_ctrl(iommu); @@ -468,7 +468,7 @@ void msi_msg_write_remap_rte( struct iommu *iommu = NULL; struct ir_ctrl *ir_ctrl; - drhd = acpi_find_matched_drhd_unit(pdev->bus, pdev->devfn); + drhd = acpi_find_matched_drhd_unit(pdev); iommu = drhd->iommu; ir_ctrl = iommu_ir_ctrl(iommu); diff -r e2ada9d65bca -r f02a528d2e56 xen/drivers/passthrough/vtd/iommu.c --- a/xen/drivers/passthrough/vtd/iommu.c Thu Mar 19 10:10:59 2009 +0000 +++ b/xen/drivers/passthrough/vtd/iommu.c Thu Mar 19 10:20:11 2009 +0000 @@ -1193,8 +1193,11 @@ static int domain_context_mapping(struct u16 sec_bus, sub_bus; u32 type; u8 secbus, secdevfn; - - drhd = acpi_find_matched_drhd_unit(bus, devfn); + struct pci_dev *pdev = pci_get_pdev(bus, devfn); + + BUG_ON(!pdev); + + drhd = acpi_find_matched_drhd_unit(pdev); if ( !drhd ) return -ENODEV; @@ -1319,8 +1322,11 @@ static int domain_context_unmap(struct d int ret = 0; u32 type; u8 secbus, secdevfn; - - drhd = acpi_find_matched_drhd_unit(bus, devfn); + struct pci_dev *pdev = pci_get_pdev(bus, devfn); + + BUG_ON(!pdev); + + drhd = acpi_find_matched_drhd_unit(pdev); if ( !drhd ) return -ENODEV; @@ -1392,7 +1398,7 @@ static int reassign_device_ownership( if (!pdev) return -ENODEV; - drhd = acpi_find_matched_drhd_unit(bus, devfn); + drhd = acpi_find_matched_drhd_unit(pdev); pdev_iommu = drhd->iommu; domain_context_unmap(source, bus, devfn); @@ -1405,7 +1411,7 @@ static int reassign_device_ownership( for_each_pdev ( source, pdev ) { - drhd = acpi_find_matched_drhd_unit(pdev->bus, pdev->devfn); + drhd = acpi_find_matched_drhd_unit(pdev); if ( drhd->iommu == pdev_iommu ) { found = 1; diff -r e2ada9d65bca -r f02a528d2e56 xen/include/public/physdev.h --- a/xen/include/public/physdev.h Thu Mar 19 10:10:59 2009 +0000 +++ b/xen/include/public/physdev.h Thu Mar 19 10:20:11 2009 +0000 @@ -183,6 +183,22 @@ typedef struct physdev_manage_pci physde typedef struct physdev_manage_pci physdev_manage_pci_t; DEFINE_XEN_GUEST_HANDLE(physdev_manage_pci_t); +#define PHYSDEVOP_manage_pci_add_ext 20 +struct physdev_manage_pci_ext { + /* IN */ + uint8_t bus; + uint8_t devfn; + unsigned is_extfn; + unsigned is_virtfn; + struct { + uint8_t bus; + uint8_t devfn; + } physfn; +}; + +typedef struct physdev_manage_pci_ext physdev_manage_pci_ext_t; +DEFINE_XEN_GUEST_HANDLE(physdev_manage_pci_ext_t); + #define PHYSDEVOP_restore_msi 19 struct physdev_restore_msi { /* IN */ diff -r e2ada9d65bca -r f02a528d2e56 xen/include/xen/pci.h --- a/xen/include/xen/pci.h Thu Mar 19 10:10:59 2009 +0000 +++ b/xen/include/xen/pci.h Thu Mar 19 10:20:11 2009 +0000 @@ -31,6 +31,15 @@ #define MAX_MSIX_TABLE_ENTRIES 2048 #define MAX_MSIX_TABLE_PAGES 8 +struct pci_dev_info { + unsigned is_extfn; + unsigned is_virtfn; + struct { + u8 bus; + u8 devfn; + } physfn; +}; + struct pci_dev { struct list_head alldevs_list; struct list_head domain_list; @@ -43,6 +52,7 @@ struct pci_dev { struct domain *domain; const u8 bus; const u8 devfn; + struct pci_dev_info info; }; #define for_each_pdev(domain, pdev) \ @@ -64,6 +74,7 @@ void pci_release_devices(struct domain * void pci_release_devices(struct domain *d); int pci_add_device(u8 bus, u8 devfn); int pci_remove_device(u8 bus, u8 devfn); +int pci_add_device_ext(u8 bus, u8 devfn, struct pci_dev_info *info); struct pci_dev *pci_get_pdev(int bus, int devfn); struct pci_dev *pci_get_pdev_by_domain(struct domain *d, int bus, int devfn); _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |