WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-devel

[Xen-devel] [PATCH 4/7] PCI device register/unregister + pci_dev cleanup

To: xen-devel@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-devel] [PATCH 4/7] PCI device register/unregister + pci_dev cleanups
From: Espen Skoglund <espen.skoglund@xxxxxxxxxxxxx>
Date: Fri, 4 Jul 2008 17:37:34 +0100
Delivery-date: Fri, 04 Jul 2008 09:39:03 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
In-reply-to: <18542.20587.995970.962113@xxxxxxxxxxxxxxxxxx>
List-help: <mailto:xen-devel-request@lists.xensource.com?subject=help>
List-id: Xen developer discussion <xen-devel.lists.xensource.com>
List-post: <mailto:xen-devel@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=unsubscribe>
References: <18542.20587.995970.962113@xxxxxxxxxxxxxxxxxx>
Sender: xen-devel-bounces@xxxxxxxxxxxxxxxxxxx
xen-pci-addremove.patch

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>

--
 arch/x86/physdev.c                      |   26 ++++++++++++++++
 drivers/passthrough/amd/pci_amd_iommu.c |   12 +++++++
 drivers/passthrough/iommu.c             |   26 ++++++++++++++++
 drivers/passthrough/pci.c               |   52 ++++++++++++++++++++++++++++++++
 drivers/passthrough/vtd/iommu.c         |   39 +++++++++++++++++-------
 include/public/physdev.h                |   11 ++++++
 include/xen/iommu.h                     |    6 ++-
 include/xen/pci.h                       |    2 +
 8 files changed, 161 insertions(+), 13 deletions(-)
--
diff -r 795e85588ded xen/arch/x86/physdev.c
--- a/xen/arch/x86/physdev.c    Fri Jul 04 16:27:50 2008 +0100
+++ b/xen/arch/x86/physdev.c    Fri Jul 04 16:31:03 2008 +0100
@@ -500,6 +500,32 @@
         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 795e85588ded xen/drivers/passthrough/amd/pci_amd_iommu.c
--- a/xen/drivers/passthrough/amd/pci_amd_iommu.c       Fri Jul 04 16:27:50 
2008 +0100
+++ b/xen/drivers/passthrough/amd/pci_amd_iommu.c       Fri Jul 04 16:31:03 
2008 +0100
@@ -628,6 +628,16 @@
     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 @@
 
 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 795e85588ded xen/drivers/passthrough/iommu.c
--- a/xen/drivers/passthrough/iommu.c   Fri Jul 04 16:27:50 2008 +0100
+++ b/xen/drivers/passthrough/iommu.c   Fri Jul 04 16:31:03 2008 +0100
@@ -53,6 +53,32 @@
     }
 
     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)
diff -r 795e85588ded xen/drivers/passthrough/pci.c
--- a/xen/drivers/passthrough/pci.c     Fri Jul 04 16:27:50 2008 +0100
+++ b/xen/drivers/passthrough/pci.c     Fri Jul 04 16:31:03 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 @@
     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 795e85588ded xen/drivers/passthrough/vtd/iommu.c
--- a/xen/drivers/passthrough/vtd/iommu.c       Fri Jul 04 16:27:50 2008 +0100
+++ b/xen/drivers/passthrough/vtd/iommu.c       Fri Jul 04 16:31:03 2008 +0100
@@ -1223,13 +1223,15 @@
     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, u8 devfn)
 {
     struct acpi_drhd_unit *drhd;
+    u16 sec_bus, sub_bus;
     int ret = 0;
     u32 type;
 
@@ -1319,10 +1322,14 @@
     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 @@
     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 @@
                 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 @@
 
 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 795e85588ded xen/include/public/physdev.h
--- a/xen/include/public/physdev.h      Fri Jul 04 16:27:50 2008 +0100
+++ b/xen/include/public/physdev.h      Fri Jul 04 16:31:03 2008 +0100
@@ -154,6 +154,17 @@
 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 795e85588ded xen/include/xen/iommu.h
--- a/xen/include/xen/iommu.h   Fri Jul 04 16:27:50 2008 +0100
+++ b/xen/include/xen/iommu.h   Fri Jul 04 16:31:03 2008 +0100
@@ -56,8 +56,8 @@
     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 @@
 
 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 795e85588ded xen/include/xen/pci.h
--- a/xen/include/xen/pci.h     Fri Jul 04 16:27:50 2008 +0100
+++ b/xen/include/xen/pci.h     Fri Jul 04 16:31:03 2008 +0100
@@ -56,6 +56,8 @@
 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-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel