[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] Add hypercall for adding and removing PCI devices
# HG changeset patch # User Keir Fraser <keir.fraser@xxxxxxxxxx> # Date 1215190370 -3600 # Node ID 183ca809e1d7d2f2f8943bd323ecc85c3968ca09 # Parent 7f7d0e7aa01bbd51f4c2045fe6b99a3f0bcd963e Add hypercall for adding and removing PCI devices The add hypercall will add a new PCI device and register it. The remove hypercall will remove the pci_dev strucure for the device. The IOMMU hardware (if present) will be notifed as well. Signed-off-by: Espen Skoglund <espen.skoglund@xxxxxxxxxxxxx> Signed-off-by: Joshua LeVasseur <joshua.levasseur@xxxxxxxxxxxxx> --- xen/arch/x86/physdev.c | 26 ++++++++++++++ xen/drivers/passthrough/amd/pci_amd_iommu.c | 12 ++++++ xen/drivers/passthrough/iommu.c | 26 ++++++++++++++ xen/drivers/passthrough/pci.c | 52 ++++++++++++++++++++++++++++ xen/drivers/passthrough/vtd/iommu.c | 39 +++++++++++++++------ xen/include/public/physdev.h | 11 +++++ xen/include/xen/iommu.h | 6 ++- xen/include/xen/pci.h | 2 + 8 files changed, 161 insertions(+), 13 deletions(-) diff -r 7f7d0e7aa01b -r 183ca809e1d7 xen/arch/x86/physdev.c --- a/xen/arch/x86/physdev.c Fri Jul 04 17:52:24 2008 +0100 +++ b/xen/arch/x86/physdev.c Fri Jul 04 17:52:50 2008 +0100 @@ -500,6 +500,32 @@ ret_t do_physdev_op(int cmd, XEN_GUEST_H break; } + case PHYSDEVOP_manage_pci_add: { + struct physdev_manage_pci manage_pci; + ret = -EPERM; + if ( !IS_PRIV(v->domain) ) + break; + ret = -EFAULT; + if ( copy_from_guest(&manage_pci, arg, 1) != 0 ) + break; + + ret = pci_add_device(manage_pci.bus, manage_pci.devfn); + break; + } + + case PHYSDEVOP_manage_pci_remove: { + struct physdev_manage_pci manage_pci; + ret = -EPERM; + if ( !IS_PRIV(v->domain) ) + break; + ret = -EFAULT; + if ( copy_from_guest(&manage_pci, arg, 1) != 0 ) + break; + + ret = pci_remove_device(manage_pci.bus, manage_pci.devfn); + break; + } + default: ret = -ENOSYS; break; diff -r 7f7d0e7aa01b -r 183ca809e1d7 xen/drivers/passthrough/amd/pci_amd_iommu.c --- a/xen/drivers/passthrough/amd/pci_amd_iommu.c Fri Jul 04 17:52:24 2008 +0100 +++ b/xen/drivers/passthrough/amd/pci_amd_iommu.c Fri Jul 04 17:52:50 2008 +0100 @@ -628,6 +628,16 @@ static int amd_iommu_return_device( return reassign_device(s, t, bus, devfn); } +static int amd_iommu_add_device(struct pci_dev *pdev) +{ + return 0; +} + +static int amd_iommu_remove_device(struct pci_dev *pdev) +{ + return 0; +} + static int amd_iommu_group_id(u8 bus, u8 devfn) { int rt; @@ -640,6 +650,8 @@ static int amd_iommu_group_id(u8 bus, u8 struct iommu_ops amd_iommu_ops = { .init = amd_iommu_domain_init, + .add_device = amd_iommu_add_device, + .remove_device = amd_iommu_remove_device, .assign_device = amd_iommu_assign_device, .teardown = amd_iommu_domain_destroy, .map_page = amd_iommu_map_page, diff -r 7f7d0e7aa01b -r 183ca809e1d7 xen/drivers/passthrough/iommu.c --- a/xen/drivers/passthrough/iommu.c Fri Jul 04 17:52:24 2008 +0100 +++ b/xen/drivers/passthrough/iommu.c Fri Jul 04 17:52:50 2008 +0100 @@ -55,6 +55,32 @@ int iommu_domain_init(struct domain *dom return hd->platform_ops->init(domain); } +int iommu_add_device(struct pci_dev *pdev) +{ + struct hvm_iommu *hd; + if ( !pdev->domain ) + return -EINVAL; + + hd = domain_hvm_iommu(pdev->domain); + if ( !iommu_enabled || !hd->platform_ops ) + return 0; + + return hd->platform_ops->add_device(pdev); +} + +int iommu_remove_device(struct pci_dev *pdev) +{ + struct hvm_iommu *hd; + if ( !pdev->domain ) + return -EINVAL; + + hd = domain_hvm_iommu(pdev->domain); + if ( !iommu_enabled || !hd->platform_ops ) + return 0; + + return hd->platform_ops->remove_device(pdev); +} + int assign_device(struct domain *d, u8 bus, u8 devfn) { struct hvm_iommu *hd = domain_hvm_iommu(d); diff -r 7f7d0e7aa01b -r 183ca809e1d7 xen/drivers/passthrough/pci.c --- a/xen/drivers/passthrough/pci.c Fri Jul 04 17:52:24 2008 +0100 +++ b/xen/drivers/passthrough/pci.c Fri Jul 04 17:52:50 2008 +0100 @@ -19,6 +19,7 @@ #include <xen/pci.h> #include <xen/list.h> #include <xen/prefetch.h> +#include <xen/iommu.h> #include <xen/keyhandler.h> @@ -93,6 +94,57 @@ struct pci_dev *pci_lock_domain_pdev(str return NULL; } +int pci_add_device(u8 bus, u8 devfn) +{ + struct pci_dev *pdev; + int ret = -ENOMEM; + + write_lock(&pcidevs_lock); + pdev = alloc_pdev(bus, devfn); + if ( !pdev ) + goto out; + + ret = 0; + spin_lock(&pdev->lock); + if ( !pdev->domain ) + { + pdev->domain = dom0; + list_add(&pdev->domain_list, &dom0->arch.pdev_list); + ret = iommu_add_device(pdev); + } + spin_unlock(&pdev->lock); + printk(XENLOG_DEBUG "PCI add device %02x:%02x.%x\n", bus, + PCI_SLOT(devfn), PCI_FUNC(devfn)); + +out: + write_unlock(&pcidevs_lock); + return ret; +} + +int pci_remove_device(u8 bus, u8 devfn) +{ + struct pci_dev *pdev; + int ret = -ENODEV;; + + write_lock(&pcidevs_lock); + list_for_each_entry ( pdev, &alldevs_list, alldevs_list ) + if ( pdev->bus == bus && pdev->devfn == devfn ) + { + spin_lock(&pdev->lock); + ret = iommu_remove_device(pdev); + if ( pdev->domain ) + list_del(&pdev->domain_list); + pci_cleanup_msi(pdev); + free_pdev(pdev); + printk(XENLOG_DEBUG "PCI remove device %02x:%02x.%x\n", bus, + PCI_SLOT(devfn), PCI_FUNC(devfn)); + break; + } + + write_unlock(&pcidevs_lock); + return ret; +} + static void dump_pci_devices(unsigned char ch) { struct pci_dev *pdev; diff -r 7f7d0e7aa01b -r 183ca809e1d7 xen/drivers/passthrough/vtd/iommu.c --- a/xen/drivers/passthrough/vtd/iommu.c Fri Jul 04 17:52:24 2008 +0100 +++ b/xen/drivers/passthrough/vtd/iommu.c Fri Jul 04 17:52:50 2008 +0100 @@ -1223,13 +1223,15 @@ static int domain_context_mapping(struct switch ( type ) { case DEV_TYPE_PCIe_BRIDGE: - break; - case DEV_TYPE_PCI_BRIDGE: sec_bus = pci_conf_read8(bus, PCI_SLOT(devfn), PCI_FUNC(devfn), PCI_SECONDARY_BUS); sub_bus = pci_conf_read8(bus, PCI_SLOT(devfn), PCI_FUNC(devfn), PCI_SUBORDINATE_BUS); + /*dmar_scope_add_buses(&drhd->scope, sec_bus, sub_bus);*/ + + if ( type == DEV_TYPE_PCIe_BRIDGE ) + break; for ( sub_bus &= 0xff; sec_bus <= sub_bus; sec_bus++ ) { @@ -1308,6 +1310,7 @@ static int domain_context_unmap(u8 bus, static int domain_context_unmap(u8 bus, u8 devfn) { struct acpi_drhd_unit *drhd; + u16 sec_bus, sub_bus; int ret = 0; u32 type; @@ -1319,10 +1322,14 @@ static int domain_context_unmap(u8 bus, switch ( type ) { case DEV_TYPE_PCIe_BRIDGE: - break; - case DEV_TYPE_PCI_BRIDGE: - ret = domain_context_unmap_one(drhd->iommu, bus, devfn); + sec_bus = pci_conf_read8(bus, PCI_SLOT(devfn), PCI_FUNC(devfn), + PCI_SECONDARY_BUS); + sub_bus = pci_conf_read8(bus, PCI_SLOT(devfn), PCI_FUNC(devfn), + PCI_SUBORDINATE_BUS); + /*dmar_scope_remove_buses(&drhd->scope, sec_bus, sub_bus);*/ + if ( DEV_TYPE_PCI_BRIDGE ) + ret = domain_context_unmap_one(drhd->iommu, bus, devfn); break; case DEV_TYPE_PCIe_ENDPOINT: @@ -1574,11 +1581,23 @@ static int iommu_prepare_rmrr_dev(struct return ret; } +static int intel_iommu_add_device(struct pci_dev *pdev) +{ + if ( !pdev->domain ) + return -EINVAL; + return domain_context_mapping(pdev->domain, pdev->bus, pdev->devfn); +} + +static int intel_iommu_remove_device(struct pci_dev *pdev) +{ + return domain_context_unmap(pdev->bus, pdev->devfn); +} + static void setup_dom0_devices(struct domain *d) { struct hvm_iommu *hd; struct pci_dev *pdev; - int bus, dev, func, ret; + int bus, dev, func; u32 l; hd = domain_hvm_iommu(d); @@ -1599,11 +1618,7 @@ static void setup_dom0_devices(struct do pdev = alloc_pdev(bus, PCI_DEVFN(dev, func)); pdev->domain = d; list_add(&pdev->domain_list, &d->arch.pdev_list); - - ret = domain_context_mapping(d, pdev->bus, pdev->devfn); - if ( ret != 0 ) - gdprintk(XENLOG_ERR VTDPREFIX, - "domain_context_mapping failed\n"); + domain_context_mapping(d, pdev->bus, pdev->devfn); } } } @@ -1866,6 +1881,8 @@ int iommu_resume(void) struct iommu_ops intel_iommu_ops = { .init = intel_iommu_domain_init, + .add_device = intel_iommu_add_device, + .remove_device = intel_iommu_remove_device, .assign_device = intel_iommu_assign_device, .teardown = iommu_domain_teardown, .map_page = intel_iommu_map_page, diff -r 7f7d0e7aa01b -r 183ca809e1d7 xen/include/public/physdev.h --- a/xen/include/public/physdev.h Fri Jul 04 17:52:24 2008 +0100 +++ b/xen/include/public/physdev.h Fri Jul 04 17:52:50 2008 +0100 @@ -154,6 +154,17 @@ typedef struct physdev_unmap_pirq physde typedef struct physdev_unmap_pirq physdev_unmap_pirq_t; DEFINE_XEN_GUEST_HANDLE(physdev_unmap_pirq_t); +#define PHYSDEVOP_manage_pci_add 15 +#define PHYSDEVOP_manage_pci_remove 16 +struct physdev_manage_pci { + /* IN */ + uint8_t bus; + uint8_t devfn; +}; + +typedef struct physdev_manage_pci physdev_manage_pci_t; +DEFINE_XEN_GUEST_HANDLE(physdev_manage_pci_t); + /* * Argument to physdev_op_compat() hypercall. Superceded by new physdev_op() * hypercall since 0x00030202. diff -r 7f7d0e7aa01b -r 183ca809e1d7 xen/include/xen/iommu.h --- a/xen/include/xen/iommu.h Fri Jul 04 17:52:24 2008 +0100 +++ b/xen/include/xen/iommu.h Fri Jul 04 17:52:50 2008 +0100 @@ -56,8 +56,8 @@ struct iommu { struct intel_iommu *intel; }; -int iommu_add_device(u8 bus, u8 devfn); -void iommu_remove_device(u8 bus, u8 devfn); +int iommu_add_device(struct pci_dev *pdev); +int iommu_remove_device(struct pci_dev *pdev); int iommu_domain_init(struct domain *d); void iommu_domain_destroy(struct domain *d); int device_assigned(u8 bus, u8 devfn); @@ -94,6 +94,8 @@ int domain_set_irq_dpci(struct domain *d struct iommu_ops { int (*init)(struct domain *d); + int (*add_device)(struct pci_dev *pdev); + int (*remove_device)(struct pci_dev *pdev); int (*assign_device)(struct domain *d, u8 bus, u8 devfn); void (*teardown)(struct domain *d); int (*map_page)(struct domain *d, unsigned long gfn, unsigned long mfn); diff -r 7f7d0e7aa01b -r 183ca809e1d7 xen/include/xen/pci.h --- a/xen/include/xen/pci.h Fri Jul 04 17:52:24 2008 +0100 +++ b/xen/include/xen/pci.h Fri Jul 04 17:52:50 2008 +0100 @@ -56,6 +56,8 @@ struct pci_dev *pci_lock_pdev(int bus, i struct pci_dev *pci_lock_pdev(int bus, int devfn); struct pci_dev *pci_lock_domain_pdev(struct domain *d, int bus, int devfn); +int pci_add_device(u8 bus, u8 devfn); +int pci_remove_device(u8 bus, u8 devfn); uint8_t pci_conf_read8( unsigned int bus, unsigned int dev, unsigned int func, unsigned int reg); _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |