mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 02:01:24 +01:00
PCI multi-seg: add new physdevop-s
The new PHYSDEVOP_pci_device_add is intended to be extensible, with a first extension (to pass the proximity domain of a device) added right away. A couple of directly related functions at once get adjusted to account for the segment number. Should we deprecate the PHYSDEVOP_manage_pci_* sub-hypercalls? Signed-off-by: Jan Beulich <jbeulich@suse.com>
This commit is contained in:
1 parent
21844b0e32
commit
7620c0cf9a
15 files changed
+241
-88
No files matched your search
@@ -665,7 +665,7 @@ long do_physdev_op(int cmd, XEN_GUEST_HANDLE(void) arg)
|
|||||||
if ( copy_from_guest(&manage_pci, arg, 1) != 0 )
|
if ( copy_from_guest(&manage_pci, arg, 1) != 0 )
|
||||||
break;
|
break;
|
||||||
|
|
||||||
ret = pci_add_device(manage_pci.bus, manage_pci.devfn, NULL);
|
ret = pci_add_device(0, manage_pci.bus, manage_pci.devfn, NULL);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -678,7 +678,7 @@ long do_physdev_op(int cmd, XEN_GUEST_HANDLE(void) arg)
|
|||||||
if ( copy_from_guest(&manage_pci, arg, 1) != 0 )
|
if ( copy_from_guest(&manage_pci, arg, 1) != 0 )
|
||||||
break;
|
break;
|
||||||
|
|
||||||
ret = pci_remove_device(manage_pci.bus, manage_pci.devfn);
|
ret = pci_remove_device(0, manage_pci.bus, manage_pci.devfn);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -698,7 +698,7 @@ long do_physdev_op(int cmd, XEN_GUEST_HANDLE(void) arg)
|
|||||||
pdev_info.is_virtfn = manage_pci_ext.is_virtfn;
|
pdev_info.is_virtfn = manage_pci_ext.is_virtfn;
|
||||||
pdev_info.physfn.bus = manage_pci_ext.physfn.bus;
|
pdev_info.physfn.bus = manage_pci_ext.physfn.bus;
|
||||||
pdev_info.physfn.devfn = manage_pci_ext.physfn.devfn;
|
pdev_info.physfn.devfn = manage_pci_ext.physfn.devfn;
|
||||||
ret = pci_add_device(manage_pci_ext.bus,
|
ret = pci_add_device(0, manage_pci_ext.bus,
|
||||||
manage_pci_ext.devfn,
|
manage_pci_ext.devfn,
|
||||||
&pdev_info);
|
&pdev_info);
|
||||||
break;
|
break;
|
||||||
|
|||||||
+1
-1
@@ -1716,7 +1716,7 @@ int map_domain_pirq(
|
|||||||
if ( !cpu_has_apic )
|
if ( !cpu_has_apic )
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
pdev = pci_get_pdev(msi->bus, msi->devfn);
|
pdev = pci_get_pdev(msi->seg, msi->bus, msi->devfn);
|
||||||
ret = pci_enable_msi(msi, &msi_desc);
|
ret = pci_enable_msi(msi, &msi_desc);
|
||||||
if ( ret )
|
if ( ret )
|
||||||
goto done;
|
goto done;
|
||||||
|
|||||||
+13
-9
@@ -528,7 +528,7 @@ static u64 read_pci_mem_bar(u8 bus, u8 slot, u8 func, u8 bir, int vf)
|
|||||||
|
|
||||||
if ( vf >= 0 )
|
if ( vf >= 0 )
|
||||||
{
|
{
|
||||||
struct pci_dev *pdev = pci_get_pdev(bus, PCI_DEVFN(slot, func));
|
struct pci_dev *pdev = pci_get_pdev(0, bus, PCI_DEVFN(slot, func));
|
||||||
unsigned int pos = pci_find_ext_capability(0, bus,
|
unsigned int pos = pci_find_ext_capability(0, bus,
|
||||||
PCI_DEVFN(slot, func),
|
PCI_DEVFN(slot, func),
|
||||||
PCI_EXT_CAP_ID_SRIOV);
|
PCI_EXT_CAP_ID_SRIOV);
|
||||||
@@ -767,7 +767,7 @@ static int __pci_enable_msi(struct msi_info *msi, struct msi_desc **desc)
|
|||||||
struct msi_desc *old_desc;
|
struct msi_desc *old_desc;
|
||||||
|
|
||||||
ASSERT(spin_is_locked(&pcidevs_lock));
|
ASSERT(spin_is_locked(&pcidevs_lock));
|
||||||
pdev = pci_get_pdev(msi->bus, msi->devfn);
|
pdev = pci_get_pdev(msi->seg, msi->bus, msi->devfn);
|
||||||
if ( !pdev )
|
if ( !pdev )
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
@@ -775,7 +775,8 @@ static int __pci_enable_msi(struct msi_info *msi, struct msi_desc **desc)
|
|||||||
if ( old_desc )
|
if ( old_desc )
|
||||||
{
|
{
|
||||||
dprintk(XENLOG_WARNING, "irq %d has already mapped to MSI on "
|
dprintk(XENLOG_WARNING, "irq %d has already mapped to MSI on "
|
||||||
"device %02x:%02x.%01x.\n", msi->irq, msi->bus,
|
"device %04x:%02x:%02x.%01x\n",
|
||||||
|
msi->irq, msi->seg, msi->bus,
|
||||||
PCI_SLOT(msi->devfn), PCI_FUNC(msi->devfn));
|
PCI_SLOT(msi->devfn), PCI_FUNC(msi->devfn));
|
||||||
*desc = old_desc;
|
*desc = old_desc;
|
||||||
return 0;
|
return 0;
|
||||||
@@ -785,7 +786,7 @@ static int __pci_enable_msi(struct msi_info *msi, struct msi_desc **desc)
|
|||||||
if ( old_desc )
|
if ( old_desc )
|
||||||
{
|
{
|
||||||
dprintk(XENLOG_WARNING, "MSI-X is already in use on "
|
dprintk(XENLOG_WARNING, "MSI-X is already in use on "
|
||||||
"device %02x:%02x.%01x\n", msi->bus,
|
"device %04x:%02x:%02x.%01x\n", msi->seg, msi->bus,
|
||||||
PCI_SLOT(msi->devfn), PCI_FUNC(msi->devfn));
|
PCI_SLOT(msi->devfn), PCI_FUNC(msi->devfn));
|
||||||
pci_disable_msi(old_desc);
|
pci_disable_msi(old_desc);
|
||||||
}
|
}
|
||||||
@@ -830,7 +831,7 @@ static int __pci_enable_msix(struct msi_info *msi, struct msi_desc **desc)
|
|||||||
struct msi_desc *old_desc;
|
struct msi_desc *old_desc;
|
||||||
|
|
||||||
ASSERT(spin_is_locked(&pcidevs_lock));
|
ASSERT(spin_is_locked(&pcidevs_lock));
|
||||||
pdev = pci_get_pdev(msi->bus, msi->devfn);
|
pdev = pci_get_pdev(msi->seg, msi->bus, msi->devfn);
|
||||||
if ( !pdev )
|
if ( !pdev )
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
@@ -844,7 +845,8 @@ static int __pci_enable_msix(struct msi_info *msi, struct msi_desc **desc)
|
|||||||
if ( old_desc )
|
if ( old_desc )
|
||||||
{
|
{
|
||||||
dprintk(XENLOG_WARNING, "irq %d has already mapped to MSIX on "
|
dprintk(XENLOG_WARNING, "irq %d has already mapped to MSIX on "
|
||||||
"device %02x:%02x.%01x.\n", msi->irq, msi->bus,
|
"device %04x:%02x:%02x.%01x\n",
|
||||||
|
msi->irq, msi->seg, msi->bus,
|
||||||
PCI_SLOT(msi->devfn), PCI_FUNC(msi->devfn));
|
PCI_SLOT(msi->devfn), PCI_FUNC(msi->devfn));
|
||||||
*desc = old_desc;
|
*desc = old_desc;
|
||||||
return 0;
|
return 0;
|
||||||
@@ -854,7 +856,7 @@ static int __pci_enable_msix(struct msi_info *msi, struct msi_desc **desc)
|
|||||||
if ( old_desc )
|
if ( old_desc )
|
||||||
{
|
{
|
||||||
dprintk(XENLOG_WARNING, "MSI is already in use on "
|
dprintk(XENLOG_WARNING, "MSI is already in use on "
|
||||||
"device %02x:%02x.%01x\n", msi->bus,
|
"device %04x:%02x:%02x.%01x\n", msi->seg, msi->bus,
|
||||||
PCI_SLOT(msi->devfn), PCI_FUNC(msi->devfn));
|
PCI_SLOT(msi->devfn), PCI_FUNC(msi->devfn));
|
||||||
pci_disable_msi(old_desc);
|
pci_disable_msi(old_desc);
|
||||||
|
|
||||||
@@ -962,8 +964,10 @@ int pci_restore_msi_state(struct pci_dev *pdev)
|
|||||||
|
|
||||||
if (desc->msi_desc != entry)
|
if (desc->msi_desc != entry)
|
||||||
{
|
{
|
||||||
dprintk(XENLOG_ERR, "Restore MSI for dev %x:%x not set before?\n",
|
dprintk(XENLOG_ERR,
|
||||||
pdev->bus, pdev->devfn);
|
"Restore MSI for dev %04x:%02x:%02x:%x not set before?\n",
|
||||||
|
pdev->seg, pdev->bus, PCI_SLOT(pdev->devfn),
|
||||||
|
PCI_FUNC(pdev->devfn));
|
||||||
spin_unlock_irqrestore(&desc->lock, flags);
|
spin_unlock_irqrestore(&desc->lock, flags);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|||||||
+73
-4
@@ -357,6 +357,15 @@ ret_t do_physdev_op(int cmd, XEN_GUEST_HANDLE(void) arg)
|
|||||||
if ( copy_from_guest(&map, arg, 1) != 0 )
|
if ( copy_from_guest(&map, arg, 1) != 0 )
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
if ( map.type == MAP_PIRQ_TYPE_MSI_SEG )
|
||||||
|
{
|
||||||
|
map.type = MAP_PIRQ_TYPE_MSI;
|
||||||
|
msi.seg = map.bus >> 16;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
msi.seg = 0;
|
||||||
|
}
|
||||||
msi.bus = map.bus;
|
msi.bus = map.bus;
|
||||||
msi.devfn = map.devfn;
|
msi.devfn = map.devfn;
|
||||||
msi.entry_nr = map.entry_nr;
|
msi.entry_nr = map.entry_nr;
|
||||||
@@ -480,7 +489,7 @@ ret_t do_physdev_op(int cmd, XEN_GUEST_HANDLE(void) arg)
|
|||||||
if ( copy_from_guest(&manage_pci, arg, 1) != 0 )
|
if ( copy_from_guest(&manage_pci, arg, 1) != 0 )
|
||||||
break;
|
break;
|
||||||
|
|
||||||
ret = pci_add_device(manage_pci.bus, manage_pci.devfn, NULL);
|
ret = pci_add_device(0, manage_pci.bus, manage_pci.devfn, NULL);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -493,7 +502,7 @@ ret_t do_physdev_op(int cmd, XEN_GUEST_HANDLE(void) arg)
|
|||||||
if ( copy_from_guest(&manage_pci, arg, 1) != 0 )
|
if ( copy_from_guest(&manage_pci, arg, 1) != 0 )
|
||||||
break;
|
break;
|
||||||
|
|
||||||
ret = pci_remove_device(manage_pci.bus, manage_pci.devfn);
|
ret = pci_remove_device(0, manage_pci.bus, manage_pci.devfn);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -517,12 +526,52 @@ ret_t do_physdev_op(int cmd, XEN_GUEST_HANDLE(void) arg)
|
|||||||
pdev_info.is_virtfn = manage_pci_ext.is_virtfn;
|
pdev_info.is_virtfn = manage_pci_ext.is_virtfn;
|
||||||
pdev_info.physfn.bus = manage_pci_ext.physfn.bus;
|
pdev_info.physfn.bus = manage_pci_ext.physfn.bus;
|
||||||
pdev_info.physfn.devfn = manage_pci_ext.physfn.devfn;
|
pdev_info.physfn.devfn = manage_pci_ext.physfn.devfn;
|
||||||
ret = pci_add_device(manage_pci_ext.bus,
|
ret = pci_add_device(0, manage_pci_ext.bus,
|
||||||
manage_pci_ext.devfn,
|
manage_pci_ext.devfn,
|
||||||
&pdev_info);
|
&pdev_info);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case PHYSDEVOP_pci_device_add: {
|
||||||
|
struct physdev_pci_device_add add;
|
||||||
|
struct pci_dev_info pdev_info;
|
||||||
|
|
||||||
|
ret = -EPERM;
|
||||||
|
if ( !IS_PRIV(current->domain) )
|
||||||
|
break;
|
||||||
|
|
||||||
|
ret = -EFAULT;
|
||||||
|
if ( copy_from_guest(&add, arg, 1) != 0 )
|
||||||
|
break;
|
||||||
|
|
||||||
|
pdev_info.is_extfn = !!(add.flags & XEN_PCI_DEV_EXTFN);
|
||||||
|
if ( add.flags & XEN_PCI_DEV_VIRTFN )
|
||||||
|
{
|
||||||
|
pdev_info.is_virtfn = 1;
|
||||||
|
pdev_info.physfn.bus = add.physfn.bus;
|
||||||
|
pdev_info.physfn.devfn = add.physfn.devfn;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
pdev_info.is_virtfn = 0;
|
||||||
|
ret = pci_add_device(add.seg, add.bus, add.devfn, &pdev_info);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case PHYSDEVOP_pci_device_remove: {
|
||||||
|
struct physdev_pci_device dev;
|
||||||
|
|
||||||
|
ret = -EPERM;
|
||||||
|
if ( !IS_PRIV(v->domain) )
|
||||||
|
break;
|
||||||
|
|
||||||
|
ret = -EFAULT;
|
||||||
|
if ( copy_from_guest(&dev, arg, 1) != 0 )
|
||||||
|
break;
|
||||||
|
|
||||||
|
ret = pci_remove_device(dev.seg, dev.bus, dev.devfn);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef __x86_64__
|
#ifdef __x86_64__
|
||||||
case PHYSDEVOP_pci_mmcfg_reserved: {
|
case PHYSDEVOP_pci_mmcfg_reserved: {
|
||||||
struct physdev_pci_mmcfg_reserved info;
|
struct physdev_pci_mmcfg_reserved info;
|
||||||
@@ -554,11 +603,31 @@ ret_t do_physdev_op(int cmd, XEN_GUEST_HANDLE(void) arg)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
spin_lock(&pcidevs_lock);
|
spin_lock(&pcidevs_lock);
|
||||||
pdev = pci_get_pdev(restore_msi.bus, restore_msi.devfn);
|
pdev = pci_get_pdev(0, restore_msi.bus, restore_msi.devfn);
|
||||||
ret = pdev ? pci_restore_msi_state(pdev) : -ENODEV;
|
ret = pdev ? pci_restore_msi_state(pdev) : -ENODEV;
|
||||||
spin_unlock(&pcidevs_lock);
|
spin_unlock(&pcidevs_lock);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case PHYSDEVOP_restore_msi_ext: {
|
||||||
|
struct physdev_pci_device dev;
|
||||||
|
struct pci_dev *pdev;
|
||||||
|
|
||||||
|
ret = -EPERM;
|
||||||
|
if ( !IS_PRIV(v->domain) )
|
||||||
|
break;
|
||||||
|
|
||||||
|
ret = -EFAULT;
|
||||||
|
if ( copy_from_guest(&dev, arg, 1) != 0 )
|
||||||
|
break;
|
||||||
|
|
||||||
|
spin_lock(&pcidevs_lock);
|
||||||
|
pdev = pci_get_pdev(dev.seg, dev.bus, dev.devfn);
|
||||||
|
ret = pdev ? pci_restore_msi_state(pdev) : -ENODEV;
|
||||||
|
spin_unlock(&pcidevs_lock);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case PHYSDEVOP_setup_gsi: {
|
case PHYSDEVOP_setup_gsi: {
|
||||||
struct physdev_setup_gsi setup_gsi;
|
struct physdev_setup_gsi setup_gsi;
|
||||||
|
|
||||||
|
|||||||
@@ -67,6 +67,14 @@ CHECK_physdev_get_free_pirq;
|
|||||||
CHECK_physdev_pci_mmcfg_reserved;
|
CHECK_physdev_pci_mmcfg_reserved;
|
||||||
#undef xen_physdev_pci_mmcfg_reserved
|
#undef xen_physdev_pci_mmcfg_reserved
|
||||||
|
|
||||||
|
#define xen_physdev_pci_device_add physdev_pci_device_add
|
||||||
|
CHECK_physdev_pci_device_add
|
||||||
|
#undef xen_physdev_pci_device_add
|
||||||
|
|
||||||
|
#define xen_physdev_pci_device physdev_pci_device
|
||||||
|
CHECK_physdev_pci_device
|
||||||
|
#undef xen_physdev_pci_device
|
||||||
|
|
||||||
#define COMPAT
|
#define COMPAT
|
||||||
#undef guest_handle_okay
|
#undef guest_handle_okay
|
||||||
#define guest_handle_okay compat_handle_okay
|
#define guest_handle_okay compat_handle_okay
|
||||||
|
|||||||
@@ -131,7 +131,7 @@ static void __init amd_iommu_setup_dom0_devices(struct domain *d)
|
|||||||
{
|
{
|
||||||
for ( devfn = 0; devfn < 256; devfn++ )
|
for ( devfn = 0; devfn < 256; devfn++ )
|
||||||
{
|
{
|
||||||
pdev = pci_get_pdev(bus, devfn);
|
pdev = pci_get_pdev(0, bus, devfn);
|
||||||
if ( !pdev )
|
if ( !pdev )
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@@ -313,7 +313,7 @@ static int reassign_device( struct domain *source, struct domain *target,
|
|||||||
struct hvm_iommu *t = domain_hvm_iommu(target);
|
struct hvm_iommu *t = domain_hvm_iommu(target);
|
||||||
|
|
||||||
ASSERT(spin_is_locked(&pcidevs_lock));
|
ASSERT(spin_is_locked(&pcidevs_lock));
|
||||||
pdev = pci_get_pdev_by_domain(source, bus, devfn);
|
pdev = pci_get_pdev_by_domain(source, 0, bus, devfn);
|
||||||
if ( !pdev )
|
if ( !pdev )
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
|
|||||||
@@ -282,7 +282,7 @@ int deassign_device(struct domain *d, u8 bus, u8 devfn)
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
ASSERT(spin_is_locked(&pcidevs_lock));
|
ASSERT(spin_is_locked(&pcidevs_lock));
|
||||||
pdev = pci_get_pdev(bus, devfn);
|
pdev = pci_get_pdev(0, bus, devfn);
|
||||||
if ( !pdev )
|
if ( !pdev )
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
|
|||||||
@@ -121,6 +121,7 @@ static struct pci_dev *alloc_pdev(struct pci_seg *pseg, u8 bus, u8 devfn)
|
|||||||
return NULL;
|
return NULL;
|
||||||
memset(pdev, 0, sizeof(struct pci_dev));
|
memset(pdev, 0, sizeof(struct pci_dev));
|
||||||
|
|
||||||
|
*(u16*) &pdev->seg = pseg->nr;
|
||||||
*((u8*) &pdev->bus) = bus;
|
*((u8*) &pdev->bus) = bus;
|
||||||
*((u8*) &pdev->devfn) = devfn;
|
*((u8*) &pdev->devfn) = devfn;
|
||||||
pdev->domain = NULL;
|
pdev->domain = NULL;
|
||||||
@@ -137,41 +138,59 @@ static void free_pdev(struct pci_dev *pdev)
|
|||||||
xfree(pdev);
|
xfree(pdev);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct pci_dev *pci_get_pdev(int bus, int devfn)
|
struct pci_dev *pci_get_pdev(int seg, int bus, int devfn)
|
||||||
{
|
{
|
||||||
struct pci_seg *pseg = get_pseg(0);
|
struct pci_seg *pseg = get_pseg(seg);
|
||||||
struct pci_dev *pdev = NULL;
|
struct pci_dev *pdev = NULL;
|
||||||
|
|
||||||
ASSERT(spin_is_locked(&pcidevs_lock));
|
ASSERT(spin_is_locked(&pcidevs_lock));
|
||||||
|
ASSERT(seg != -1 || bus == -1);
|
||||||
|
ASSERT(bus != -1 || devfn == -1);
|
||||||
|
|
||||||
if ( !pseg )
|
if ( !pseg )
|
||||||
return NULL;
|
{
|
||||||
|
if ( seg == -1 )
|
||||||
|
radix_tree_gang_lookup(&pci_segments, (void **)&pseg, 0, 1);
|
||||||
|
if ( !pseg )
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
list_for_each_entry ( pdev, &pseg->alldevs_list, alldevs_list )
|
do {
|
||||||
if ( (pdev->bus == bus || bus == -1) &&
|
list_for_each_entry ( pdev, &pseg->alldevs_list, alldevs_list )
|
||||||
(pdev->devfn == devfn || devfn == -1) )
|
if ( (pdev->bus == bus || bus == -1) &&
|
||||||
{
|
(pdev->devfn == devfn || devfn == -1) )
|
||||||
return pdev;
|
return pdev;
|
||||||
}
|
} while ( radix_tree_gang_lookup(&pci_segments, (void **)&pseg,
|
||||||
|
pseg->nr + 1, 1) );
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct pci_dev *pci_get_pdev_by_domain(struct domain *d, int bus, int devfn)
|
struct pci_dev *pci_get_pdev_by_domain(
|
||||||
|
struct domain *d, int seg, int bus, int devfn)
|
||||||
{
|
{
|
||||||
struct pci_seg *pseg = get_pseg(0);
|
struct pci_seg *pseg = get_pseg(seg);
|
||||||
struct pci_dev *pdev = NULL;
|
struct pci_dev *pdev = NULL;
|
||||||
|
|
||||||
if ( !pseg )
|
ASSERT(seg != -1 || bus == -1);
|
||||||
return NULL;
|
ASSERT(bus != -1 || devfn == -1);
|
||||||
|
|
||||||
list_for_each_entry ( pdev, &pseg->alldevs_list, alldevs_list )
|
if ( !pseg )
|
||||||
if ( (pdev->bus == bus || bus == -1) &&
|
{
|
||||||
(pdev->devfn == devfn || devfn == -1) &&
|
if ( seg == -1 )
|
||||||
(pdev->domain == d) )
|
radix_tree_gang_lookup(&pci_segments, (void **)&pseg, 0, 1);
|
||||||
{
|
if ( !pseg )
|
||||||
return pdev;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
do {
|
||||||
|
list_for_each_entry ( pdev, &pseg->alldevs_list, alldevs_list )
|
||||||
|
if ( (pdev->bus == bus || bus == -1) &&
|
||||||
|
(pdev->devfn == devfn || devfn == -1) &&
|
||||||
|
(pdev->domain == d) )
|
||||||
|
return pdev;
|
||||||
|
} while ( radix_tree_gang_lookup(&pci_segments, (void **)&pseg,
|
||||||
|
pseg->nr + 1, 1) );
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -215,7 +234,7 @@ void pci_enable_acs(struct pci_dev *pdev)
|
|||||||
pci_conf_write16(bus, dev, func, pos + PCI_ACS_CTRL, ctrl);
|
pci_conf_write16(bus, dev, func, pos + PCI_ACS_CTRL, ctrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
int pci_add_device(u8 bus, u8 devfn, const struct pci_dev_info *info)
|
int pci_add_device(u16 seg, u8 bus, u8 devfn, const struct pci_dev_info *info)
|
||||||
{
|
{
|
||||||
struct pci_seg *pseg;
|
struct pci_seg *pseg;
|
||||||
struct pci_dev *pdev;
|
struct pci_dev *pdev;
|
||||||
@@ -230,17 +249,20 @@ int pci_add_device(u8 bus, u8 devfn, const struct pci_dev_info *info)
|
|||||||
else if (info->is_virtfn)
|
else if (info->is_virtfn)
|
||||||
{
|
{
|
||||||
spin_lock(&pcidevs_lock);
|
spin_lock(&pcidevs_lock);
|
||||||
pdev = pci_get_pdev(info->physfn.bus, info->physfn.devfn);
|
pdev = pci_get_pdev(seg, info->physfn.bus, info->physfn.devfn);
|
||||||
spin_unlock(&pcidevs_lock);
|
spin_unlock(&pcidevs_lock);
|
||||||
if ( !pdev )
|
if ( !pdev )
|
||||||
pci_add_device(info->physfn.bus, info->physfn.devfn, NULL);
|
pci_add_device(seg, info->physfn.bus, info->physfn.devfn, NULL);
|
||||||
pdev_type = "virtual function";
|
pdev_type = "virtual function";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return -EINVAL;
|
{
|
||||||
|
info = NULL;
|
||||||
|
pdev_type = "device";
|
||||||
|
}
|
||||||
|
|
||||||
spin_lock(&pcidevs_lock);
|
spin_lock(&pcidevs_lock);
|
||||||
pseg = alloc_pseg(0);
|
pseg = alloc_pseg(seg);
|
||||||
if ( !pseg )
|
if ( !pseg )
|
||||||
goto out;
|
goto out;
|
||||||
pdev = alloc_pdev(pseg, bus, devfn);
|
pdev = alloc_pdev(pseg, bus, devfn);
|
||||||
@@ -251,7 +273,7 @@ int pci_add_device(u8 bus, u8 devfn, const struct pci_dev_info *info)
|
|||||||
pdev->info = *info;
|
pdev->info = *info;
|
||||||
else if ( !pdev->vf_rlen[0] )
|
else if ( !pdev->vf_rlen[0] )
|
||||||
{
|
{
|
||||||
unsigned int pos = pci_find_ext_capability(0, bus, devfn,
|
unsigned int pos = pci_find_ext_capability(seg, bus, devfn,
|
||||||
PCI_EXT_CAP_ID_SRIOV);
|
PCI_EXT_CAP_ID_SRIOV);
|
||||||
u16 ctrl = pci_conf_read16(bus, slot, func, pos + PCI_SRIOV_CTRL);
|
u16 ctrl = pci_conf_read16(bus, slot, func, pos + PCI_SRIOV_CTRL);
|
||||||
|
|
||||||
@@ -271,9 +293,10 @@ int pci_add_device(u8 bus, u8 devfn, const struct pci_dev_info *info)
|
|||||||
if ( (bar & PCI_BASE_ADDRESS_SPACE) ==
|
if ( (bar & PCI_BASE_ADDRESS_SPACE) ==
|
||||||
PCI_BASE_ADDRESS_SPACE_IO )
|
PCI_BASE_ADDRESS_SPACE_IO )
|
||||||
{
|
{
|
||||||
printk(XENLOG_WARNING "SR-IOV device %02x:%02x.%x with vf"
|
printk(XENLOG_WARNING
|
||||||
" BAR%u in IO space\n",
|
"SR-IOV device %04x:%02x:%02x.%u with vf BAR%u"
|
||||||
bus, slot, func, i);
|
" in IO space\n",
|
||||||
|
seg, bus, slot, func, i);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
pci_conf_write32(bus, slot, func, idx, ~0);
|
pci_conf_write32(bus, slot, func, idx, ~0);
|
||||||
@@ -282,9 +305,10 @@ int pci_add_device(u8 bus, u8 devfn, const struct pci_dev_info *info)
|
|||||||
{
|
{
|
||||||
if ( i >= PCI_SRIOV_NUM_BARS )
|
if ( i >= PCI_SRIOV_NUM_BARS )
|
||||||
{
|
{
|
||||||
printk(XENLOG_WARNING "SR-IOV device %02x:%02x.%x with"
|
printk(XENLOG_WARNING
|
||||||
" 64-bit vf BAR in last slot\n",
|
"SR-IOV device %04x:%02x:%02x.%u with 64-bit"
|
||||||
bus, slot, func);
|
" vf BAR in last slot\n",
|
||||||
|
seg, bus, slot, func);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
hi = pci_conf_read32(bus, slot, func, idx + 4);
|
hi = pci_conf_read32(bus, slot, func, idx + 4);
|
||||||
@@ -309,9 +333,10 @@ int pci_add_device(u8 bus, u8 devfn, const struct pci_dev_info *info)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
printk(XENLOG_WARNING "SR-IOV device %02x:%02x.%x has its virtual"
|
printk(XENLOG_WARNING
|
||||||
" functions already enabled (%04x)\n",
|
"SR-IOV device %04x:%02x:%02x.%u has its virtual"
|
||||||
bus, slot, func, ctrl);
|
" functions already enabled (%04x)\n",
|
||||||
|
seg, bus, slot, func, ctrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = 0;
|
ret = 0;
|
||||||
@@ -331,14 +356,14 @@ int pci_add_device(u8 bus, u8 devfn, const struct pci_dev_info *info)
|
|||||||
|
|
||||||
out:
|
out:
|
||||||
spin_unlock(&pcidevs_lock);
|
spin_unlock(&pcidevs_lock);
|
||||||
printk(XENLOG_DEBUG "PCI add %s %02x:%02x.%x\n", pdev_type,
|
printk(XENLOG_DEBUG "PCI add %s %04x:%02x:%02x.%u\n", pdev_type,
|
||||||
bus, slot, func);
|
seg, bus, slot, func);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int pci_remove_device(u8 bus, u8 devfn)
|
int pci_remove_device(u16 seg, u8 bus, u8 devfn)
|
||||||
{
|
{
|
||||||
struct pci_seg *pseg = get_pseg(0);
|
struct pci_seg *pseg = get_pseg(seg);
|
||||||
struct pci_dev *pdev;
|
struct pci_dev *pdev;
|
||||||
int ret = -ENODEV;
|
int ret = -ENODEV;
|
||||||
|
|
||||||
@@ -354,8 +379,8 @@ int pci_remove_device(u8 bus, u8 devfn)
|
|||||||
list_del(&pdev->domain_list);
|
list_del(&pdev->domain_list);
|
||||||
pci_cleanup_msi(pdev);
|
pci_cleanup_msi(pdev);
|
||||||
free_pdev(pdev);
|
free_pdev(pdev);
|
||||||
printk(XENLOG_DEBUG "PCI remove device %02x:%02x.%x\n", bus,
|
printk(XENLOG_DEBUG "PCI remove device %04x:%02x:%02x.%u\n",
|
||||||
PCI_SLOT(devfn), PCI_FUNC(devfn));
|
seg, bus, PCI_SLOT(devfn), PCI_FUNC(devfn));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -413,7 +438,7 @@ void pci_release_devices(struct domain *d)
|
|||||||
|
|
||||||
spin_lock(&pcidevs_lock);
|
spin_lock(&pcidevs_lock);
|
||||||
pci_clean_dpci_irqs(d);
|
pci_clean_dpci_irqs(d);
|
||||||
while ( (pdev = pci_get_pdev_by_domain(d, -1, -1)) )
|
while ( (pdev = pci_get_pdev_by_domain(d, -1, -1, -1)) )
|
||||||
{
|
{
|
||||||
pci_cleanup_msi(pdev);
|
pci_cleanup_msi(pdev);
|
||||||
bus = pdev->bus; devfn = pdev->devfn;
|
bus = pdev->bus; devfn = pdev->devfn;
|
||||||
|
|||||||
@@ -280,7 +280,7 @@ static u64 addr_to_dma_page_maddr(struct domain *domain, u64 addr, int alloc)
|
|||||||
* just get any passthrough device in the domainr - assume user
|
* just get any passthrough device in the domainr - assume user
|
||||||
* assigns only devices from same node to a given guest.
|
* assigns only devices from same node to a given guest.
|
||||||
*/
|
*/
|
||||||
pdev = pci_get_pdev_by_domain(domain, -1, -1);
|
pdev = pci_get_pdev_by_domain(domain, -1, -1, -1);
|
||||||
drhd = acpi_find_matched_drhd_unit(pdev);
|
drhd = acpi_find_matched_drhd_unit(pdev);
|
||||||
if ( !alloc || ((hd->pgd_maddr = alloc_pgtable_maddr(drhd, 1)) == 0) )
|
if ( !alloc || ((hd->pgd_maddr = alloc_pgtable_maddr(drhd, 1)) == 0) )
|
||||||
goto out;
|
goto out;
|
||||||
@@ -297,7 +297,7 @@ static u64 addr_to_dma_page_maddr(struct domain *domain, u64 addr, int alloc)
|
|||||||
if ( !alloc )
|
if ( !alloc )
|
||||||
break;
|
break;
|
||||||
|
|
||||||
pdev = pci_get_pdev_by_domain(domain, -1, -1);
|
pdev = pci_get_pdev_by_domain(domain, -1, -1, -1);
|
||||||
drhd = acpi_find_matched_drhd_unit(pdev);
|
drhd = acpi_find_matched_drhd_unit(pdev);
|
||||||
maddr = alloc_pgtable_maddr(drhd, 1);
|
maddr = alloc_pgtable_maddr(drhd, 1);
|
||||||
if ( !maddr )
|
if ( !maddr )
|
||||||
@@ -1273,7 +1273,7 @@ int domain_context_mapping_one(
|
|||||||
|
|
||||||
/* First try to get domain ownership from device structure. If that's
|
/* First try to get domain ownership from device structure. If that's
|
||||||
* not available, try to read it from the context itself. */
|
* not available, try to read it from the context itself. */
|
||||||
pdev = pci_get_pdev(bus, devfn);
|
pdev = pci_get_pdev(0, bus, devfn);
|
||||||
if ( pdev )
|
if ( pdev )
|
||||||
{
|
{
|
||||||
if ( pdev->domain != domain )
|
if ( pdev->domain != domain )
|
||||||
@@ -1396,7 +1396,7 @@ static int domain_context_mapping(struct domain *domain, u8 bus, u8 devfn)
|
|||||||
int ret = 0;
|
int ret = 0;
|
||||||
u32 type;
|
u32 type;
|
||||||
u8 secbus;
|
u8 secbus;
|
||||||
struct pci_dev *pdev = pci_get_pdev(bus, devfn);
|
struct pci_dev *pdev = pci_get_pdev(0, bus, devfn);
|
||||||
|
|
||||||
drhd = acpi_find_matched_drhd_unit(pdev);
|
drhd = acpi_find_matched_drhd_unit(pdev);
|
||||||
if ( !drhd )
|
if ( !drhd )
|
||||||
@@ -1521,7 +1521,7 @@ static int domain_context_unmap(struct domain *domain, u8 bus, u8 devfn)
|
|||||||
int ret = 0;
|
int ret = 0;
|
||||||
u32 type;
|
u32 type;
|
||||||
u8 tmp_bus, tmp_devfn, secbus;
|
u8 tmp_bus, tmp_devfn, secbus;
|
||||||
struct pci_dev *pdev = pci_get_pdev(bus, devfn);
|
struct pci_dev *pdev = pci_get_pdev(0, bus, devfn);
|
||||||
int found = 0;
|
int found = 0;
|
||||||
|
|
||||||
BUG_ON(!pdev);
|
BUG_ON(!pdev);
|
||||||
@@ -1632,7 +1632,7 @@ static int reassign_device_ownership(
|
|||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ASSERT(spin_is_locked(&pcidevs_lock));
|
ASSERT(spin_is_locked(&pcidevs_lock));
|
||||||
pdev = pci_get_pdev_by_domain(source, bus, devfn);
|
pdev = pci_get_pdev_by_domain(source, 0, bus, devfn);
|
||||||
|
|
||||||
if (!pdev)
|
if (!pdev)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
@@ -1941,7 +1941,7 @@ static void __init setup_dom0_devices(struct domain *d)
|
|||||||
{
|
{
|
||||||
for ( devfn = 0; devfn < 256; devfn++ )
|
for ( devfn = 0; devfn < 256; devfn++ )
|
||||||
{
|
{
|
||||||
pdev = pci_get_pdev(bus, devfn);
|
pdev = pci_get_pdev(0, bus, devfn);
|
||||||
if ( !pdev )
|
if ( !pdev )
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@@ -2175,7 +2175,7 @@ int device_assigned(u8 bus, u8 devfn)
|
|||||||
struct pci_dev *pdev;
|
struct pci_dev *pdev;
|
||||||
|
|
||||||
spin_lock(&pcidevs_lock);
|
spin_lock(&pcidevs_lock);
|
||||||
pdev = pci_get_pdev_by_domain(dom0, bus, devfn);
|
pdev = pci_get_pdev_by_domain(dom0, 0, bus, devfn);
|
||||||
if (!pdev)
|
if (!pdev)
|
||||||
{
|
{
|
||||||
spin_unlock(&pcidevs_lock);
|
spin_unlock(&pcidevs_lock);
|
||||||
@@ -2197,7 +2197,7 @@ static int intel_iommu_assign_device(struct domain *d, u8 bus, u8 devfn)
|
|||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
ASSERT(spin_is_locked(&pcidevs_lock));
|
ASSERT(spin_is_locked(&pcidevs_lock));
|
||||||
pdev = pci_get_pdev(bus, devfn);
|
pdev = pci_get_pdev(0, bus, devfn);
|
||||||
if (!pdev)
|
if (!pdev)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
|
|||||||
@@ -286,7 +286,7 @@ static void map_me_phantom_function(struct domain *domain, u32 dev, int map)
|
|||||||
struct pci_dev *pdev;
|
struct pci_dev *pdev;
|
||||||
|
|
||||||
/* find ME VT-d engine base on a real ME device */
|
/* find ME VT-d engine base on a real ME device */
|
||||||
pdev = pci_get_pdev(0, PCI_DEVFN(dev, 0));
|
pdev = pci_get_pdev(0, 0, PCI_DEVFN(dev, 0));
|
||||||
drhd = acpi_find_matched_drhd_unit(pdev);
|
drhd = acpi_find_matched_drhd_unit(pdev);
|
||||||
|
|
||||||
/* map or unmap ME phantom function */
|
/* map or unmap ME phantom function */
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ static LIST_HEAD(ats_dev_drhd_units);
|
|||||||
|
|
||||||
struct pci_ats_dev {
|
struct pci_ats_dev {
|
||||||
struct list_head list;
|
struct list_head list;
|
||||||
|
u16 seg;
|
||||||
u8 bus;
|
u8 bus;
|
||||||
u8 devfn;
|
u8 devfn;
|
||||||
u16 ats_queue_depth; /* ATS device invalidation queue depth */
|
u16 ats_queue_depth; /* ATS device invalidation queue depth */
|
||||||
@@ -91,7 +92,7 @@ int ats_device(int seg, int bus, int devfn)
|
|||||||
if ( !ats_enabled || !iommu_qinval )
|
if ( !ats_enabled || !iommu_qinval )
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
pdev = pci_get_pdev(bus, devfn);
|
pdev = pci_get_pdev(seg, bus, devfn);
|
||||||
if ( !pdev )
|
if ( !pdev )
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@@ -130,8 +131,9 @@ int enable_ats_device(int seg, int bus, int devfn)
|
|||||||
BUG_ON(!pos);
|
BUG_ON(!pos);
|
||||||
|
|
||||||
if ( iommu_verbose )
|
if ( iommu_verbose )
|
||||||
dprintk(XENLOG_INFO VTDPREFIX, "%x:%x.%x: ATS capability found\n",
|
dprintk(XENLOG_INFO VTDPREFIX,
|
||||||
bus, PCI_SLOT(devfn), PCI_FUNC(devfn));
|
"%04x:%02x:%02x.%u: ATS capability found\n",
|
||||||
|
seg, bus, PCI_SLOT(devfn), PCI_FUNC(devfn));
|
||||||
|
|
||||||
/* BUGBUG: add back seg when multi-seg platform support is enabled */
|
/* BUGBUG: add back seg when multi-seg platform support is enabled */
|
||||||
value = pci_conf_read16(bus, PCI_SLOT(devfn),
|
value = pci_conf_read16(bus, PCI_SLOT(devfn),
|
||||||
@@ -140,7 +142,7 @@ int enable_ats_device(int seg, int bus, int devfn)
|
|||||||
{
|
{
|
||||||
list_for_each_entry ( pdev, &ats_devices, list )
|
list_for_each_entry ( pdev, &ats_devices, list )
|
||||||
{
|
{
|
||||||
if ( pdev->bus == bus && pdev->devfn == devfn )
|
if ( pdev->seg == seg && pdev->bus == bus && pdev->devfn == devfn )
|
||||||
{
|
{
|
||||||
pos = 0;
|
pos = 0;
|
||||||
break;
|
break;
|
||||||
@@ -161,6 +163,7 @@ int enable_ats_device(int seg, int bus, int devfn)
|
|||||||
|
|
||||||
if ( pos )
|
if ( pos )
|
||||||
{
|
{
|
||||||
|
pdev->seg = seg;
|
||||||
pdev->bus = bus;
|
pdev->bus = bus;
|
||||||
pdev->devfn = devfn;
|
pdev->devfn = devfn;
|
||||||
value = pci_conf_read16(bus, PCI_SLOT(devfn),
|
value = pci_conf_read16(bus, PCI_SLOT(devfn),
|
||||||
@@ -170,8 +173,10 @@ int enable_ats_device(int seg, int bus, int devfn)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ( iommu_verbose )
|
if ( iommu_verbose )
|
||||||
dprintk(XENLOG_INFO VTDPREFIX, "%x:%x.%x: ATS %s enabled\n",
|
dprintk(XENLOG_INFO VTDPREFIX,
|
||||||
bus, PCI_SLOT(devfn), PCI_FUNC(devfn), pos ? "is" : "was");
|
"%04x:%02x:%02x.%u: ATS %s enabled\n",
|
||||||
|
seg, bus, PCI_SLOT(devfn), PCI_FUNC(devfn),
|
||||||
|
pos ? "is" : "was");
|
||||||
|
|
||||||
return pos;
|
return pos;
|
||||||
}
|
}
|
||||||
@@ -194,7 +199,7 @@ void disable_ats_device(int seg, int bus, int devfn)
|
|||||||
|
|
||||||
list_for_each_entry ( pdev, &ats_devices, list )
|
list_for_each_entry ( pdev, &ats_devices, list )
|
||||||
{
|
{
|
||||||
if ( pdev->bus == bus && pdev->devfn == devfn )
|
if ( pdev->seg == seg && pdev->bus == bus && pdev->devfn == devfn )
|
||||||
{
|
{
|
||||||
list_del(&pdev->list);
|
list_del(&pdev->list);
|
||||||
xfree(pdev);
|
xfree(pdev);
|
||||||
@@ -203,8 +208,9 @@ void disable_ats_device(int seg, int bus, int devfn)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ( iommu_verbose )
|
if ( iommu_verbose )
|
||||||
dprintk(XENLOG_INFO VTDPREFIX, "%x:%x.%x: ATS is disabled\n",
|
dprintk(XENLOG_INFO VTDPREFIX,
|
||||||
bus, PCI_SLOT(devfn), PCI_FUNC(devfn));
|
"%04x:%02x:%02x.%u: ATS is disabled\n",
|
||||||
|
seg, bus, PCI_SLOT(devfn), PCI_FUNC(devfn));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -59,8 +59,9 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct msi_info {
|
struct msi_info {
|
||||||
int bus;
|
u16 seg;
|
||||||
int devfn;
|
u8 bus;
|
||||||
|
u8 devfn;
|
||||||
int irq;
|
int irq;
|
||||||
int entry_nr;
|
int entry_nr;
|
||||||
uint64_t table_base;
|
uint64_t table_base;
|
||||||
|
|||||||
@@ -142,6 +142,7 @@ DEFINE_XEN_GUEST_HANDLE(physdev_irq_t);
|
|||||||
#define MAP_PIRQ_TYPE_MSI 0x0
|
#define MAP_PIRQ_TYPE_MSI 0x0
|
||||||
#define MAP_PIRQ_TYPE_GSI 0x1
|
#define MAP_PIRQ_TYPE_GSI 0x1
|
||||||
#define MAP_PIRQ_TYPE_UNKNOWN 0x2
|
#define MAP_PIRQ_TYPE_UNKNOWN 0x2
|
||||||
|
#define MAP_PIRQ_TYPE_MSI_SEG 0x3
|
||||||
|
|
||||||
#define PHYSDEVOP_map_pirq 13
|
#define PHYSDEVOP_map_pirq 13
|
||||||
struct physdev_map_pirq {
|
struct physdev_map_pirq {
|
||||||
@@ -152,7 +153,7 @@ struct physdev_map_pirq {
|
|||||||
int index;
|
int index;
|
||||||
/* IN or OUT */
|
/* IN or OUT */
|
||||||
int pirq;
|
int pirq;
|
||||||
/* IN */
|
/* IN - high 16 bits hold segment for MAP_PIRQ_TYPE_MSI_SEG */
|
||||||
int bus;
|
int bus;
|
||||||
/* IN */
|
/* IN */
|
||||||
int devfn;
|
int devfn;
|
||||||
@@ -268,6 +269,41 @@ struct physdev_pci_mmcfg_reserved {
|
|||||||
typedef struct physdev_pci_mmcfg_reserved physdev_pci_mmcfg_reserved_t;
|
typedef struct physdev_pci_mmcfg_reserved physdev_pci_mmcfg_reserved_t;
|
||||||
DEFINE_XEN_GUEST_HANDLE(physdev_pci_mmcfg_reserved_t);
|
DEFINE_XEN_GUEST_HANDLE(physdev_pci_mmcfg_reserved_t);
|
||||||
|
|
||||||
|
#define XEN_PCI_DEV_EXTFN 0x1
|
||||||
|
#define XEN_PCI_DEV_VIRTFN 0x2
|
||||||
|
#define XEN_PCI_DEV_PXM 0x4
|
||||||
|
|
||||||
|
#define PHYSDEVOP_pci_device_add 25
|
||||||
|
struct physdev_pci_device_add {
|
||||||
|
/* IN */
|
||||||
|
uint16_t seg;
|
||||||
|
uint8_t bus;
|
||||||
|
uint8_t devfn;
|
||||||
|
uint32_t flags;
|
||||||
|
struct {
|
||||||
|
uint8_t bus;
|
||||||
|
uint8_t devfn;
|
||||||
|
} physfn;
|
||||||
|
#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
|
||||||
|
uint32_t optarr[];
|
||||||
|
#elif defined(__GNUC__)
|
||||||
|
uint32_t optarr[0];
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
typedef struct physdev_pci_device_add physdev_pci_device_add_t;
|
||||||
|
DEFINE_XEN_GUEST_HANDLE(physdev_pci_device_add_t);
|
||||||
|
|
||||||
|
#define PHYSDEVOP_pci_device_remove 26
|
||||||
|
#define PHYSDEVOP_restore_msi_ext 27
|
||||||
|
struct physdev_pci_device {
|
||||||
|
/* IN */
|
||||||
|
uint16_t seg;
|
||||||
|
uint8_t bus;
|
||||||
|
uint8_t devfn;
|
||||||
|
};
|
||||||
|
typedef struct physdev_pci_device physdev_pci_device_t;
|
||||||
|
DEFINE_XEN_GUEST_HANDLE(physdev_pci_device_t);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Notify that some PIRQ-bound event channels have been unmasked.
|
* Notify that some PIRQ-bound event channels have been unmasked.
|
||||||
* ** This command is obsolete since interface version 0x00030202 and is **
|
* ** This command is obsolete since interface version 0x00030202 and is **
|
||||||
|
|||||||
@@ -56,6 +56,7 @@ struct pci_dev {
|
|||||||
spinlock_t msix_table_lock;
|
spinlock_t msix_table_lock;
|
||||||
|
|
||||||
struct domain *domain;
|
struct domain *domain;
|
||||||
|
const u16 seg;
|
||||||
const u8 bus;
|
const u8 bus;
|
||||||
const u8 devfn;
|
const u8 devfn;
|
||||||
struct pci_dev_info info;
|
struct pci_dev_info info;
|
||||||
@@ -90,10 +91,11 @@ struct pci_dev *pci_lock_domain_pdev(struct domain *d, int bus, int devfn);
|
|||||||
|
|
||||||
void pci_release_devices(struct domain *d);
|
void pci_release_devices(struct domain *d);
|
||||||
int pci_add_segment(u16 seg);
|
int pci_add_segment(u16 seg);
|
||||||
int pci_add_device(u8 bus, u8 devfn, const struct pci_dev_info *);
|
int pci_add_device(u16 seg, u8 bus, u8 devfn, const struct pci_dev_info *);
|
||||||
int pci_remove_device(u8 bus, u8 devfn);
|
int pci_remove_device(u16 seg, u8 bus, u8 devfn);
|
||||||
struct pci_dev *pci_get_pdev(int bus, int devfn);
|
struct pci_dev *pci_get_pdev(int seg, int bus, int devfn);
|
||||||
struct pci_dev *pci_get_pdev_by_domain(struct domain *d, int bus, int devfn);
|
struct pci_dev *pci_get_pdev_by_domain(
|
||||||
|
struct domain *, int seg, int bus, int devfn);
|
||||||
|
|
||||||
void disconnect_pci_devices(void);
|
void disconnect_pci_devices(void);
|
||||||
|
|
||||||
|
|||||||
@@ -65,6 +65,8 @@
|
|||||||
? physdev_irq_status_query physdev.h
|
? physdev_irq_status_query physdev.h
|
||||||
? physdev_manage_pci physdev.h
|
? physdev_manage_pci physdev.h
|
||||||
? physdev_manage_pci_ext physdev.h
|
? physdev_manage_pci_ext physdev.h
|
||||||
|
? physdev_pci_device physdev.h
|
||||||
|
? physdev_pci_device_add physdev.h
|
||||||
? physdev_pci_mmcfg_reserved physdev.h
|
? physdev_pci_mmcfg_reserved physdev.h
|
||||||
? physdev_unmap_pirq physdev.h
|
? physdev_unmap_pirq physdev.h
|
||||||
? physdev_restore_msi physdev.h
|
? physdev_restore_msi physdev.h
|
||||||
|
|||||||