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-changelog

[Xen-changelog] [xen-unstable] Add hypercall for adding and removing PCI

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [xen-unstable] Add hypercall for adding and removing PCI devices
From: Xen patchbot-unstable <patchbot-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Fri, 04 Jul 2008 16:20:14 -0700
Delivery-date: Fri, 04 Jul 2008 16:20:40 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-changelog-request@lists.xensource.com?subject=help>
List-id: BK change log <xen-changelog.lists.xensource.com>
List-post: <mailto:xen-changelog@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=unsubscribe>
Reply-to: xen-devel@xxxxxxxxxxxxxxxxxxx
Sender: xen-changelog-bounces@xxxxxxxxxxxxxxxxxxx
# 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

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] [xen-unstable] Add hypercall for adding and removing PCI devices, Xen patchbot-unstable <=