# HG changeset patch # User Yu Zhao # Date 1237441331 14400 # Node ID a5d36fbbdea4c1fa0b925689834cf6775066f6f1 # Parent 4839e34e67952b540fa258811324a85ace7feb79 PCI: pass ARI and SR-IOV device information to the hypervisor 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 diff -r 4839e34e6795 -r a5d36fbbdea4 drivers/xen/core/pci.c --- a/drivers/xen/core/pci.c Wed Mar 18 15:43:57 2009 +0000 +++ b/drivers/xen/core/pci.c Thu Mar 19 01:42:11 2009 -0400 @@ -6,6 +6,7 @@ #include #include #include +#include "../../pci/pci.h" static int (*pci_bus_probe)(struct device *dev); static int (*pci_bus_remove)(struct device *dev); @@ -15,10 +16,30 @@ int r; struct pci_dev *pci_dev = to_pci_dev(dev); struct physdev_manage_pci manage_pci; - manage_pci.bus = pci_dev->bus->number; - manage_pci.devfn = pci_dev->devfn; + struct physdev_manage_pci_ext manage_pci_ext; - r = HYPERVISOR_physdev_op(PHYSDEVOP_manage_pci_add, &manage_pci); + if (pci_dev->is_virtfn) { + memset(&manage_pci_ext, 0, sizeof(manage_pci_ext)); + manage_pci_ext.bus = pci_dev->bus->number; + manage_pci_ext.devfn = pci_dev->devfn; + manage_pci_ext.is_virtfn = 1; + manage_pci_ext.physfn.bus = pci_dev->physfn->bus->number; + manage_pci_ext.physfn.devfn = pci_dev->physfn->devfn; + r = HYPERVISOR_physdev_op(PHYSDEVOP_manage_pci_add_ext, + &manage_pci_ext); + } else if (pci_ari_enabled(pci_dev->bus) && PCI_SLOT(pci_dev->devfn)) { + memset(&manage_pci_ext, 0, sizeof(manage_pci_ext)); + manage_pci_ext.bus = pci_dev->bus->number; + manage_pci_ext.devfn = pci_dev->devfn; + manage_pci_ext.is_extfn = 1; + r = HYPERVISOR_physdev_op(PHYSDEVOP_manage_pci_add_ext, + &manage_pci_ext); + } else { + manage_pci.bus = pci_dev->bus->number; + manage_pci.devfn = pci_dev->devfn; + r = HYPERVISOR_physdev_op(PHYSDEVOP_manage_pci_add, + &manage_pci); + } if (r && r != -ENOSYS) return r; diff -r 4839e34e6795 -r a5d36fbbdea4 include/xen/interface/physdev.h --- a/include/xen/interface/physdev.h Wed Mar 18 15:43:57 2009 +0000 +++ b/include/xen/interface/physdev.h Thu Mar 19 01:42:11 2009 -0400 @@ -192,6 +192,22 @@ typedef struct physdev_restore_msi physdev_restore_msi_t; DEFINE_XEN_GUEST_HANDLE(physdev_restore_msi_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); + /* * Argument to physdev_op_compat() hypercall. Superceded by new physdev_op() * hypercall since 0x00030202.