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] PCI multi-seg: adjust domctl interface

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [xen-unstable] PCI multi-seg: adjust domctl interface
From: Xen patchbot-unstable <patchbot@xxxxxxx>
Date: Wed, 28 Sep 2011 02:55:09 +0100
Delivery-date: Tue, 27 Sep 2011 18:56:29 -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 Jan Beulich <jbeulich@xxxxxxxx>
# Date 1316712414 -3600
# Node ID ec7c81fbe0de9b18f38bf2592a9e44d0992821c9
# Parent  a422e2a4451e16dc791b293f41966b842fa4781d
PCI multi-seg: adjust domctl interface

Again, a couple of directly related functions at once get adjusted to
account for the segment number.

Signed-off-by: Jan Beulich <jbeulich@xxxxxxxx>
---


diff -r a422e2a4451e -r ec7c81fbe0de tools/libxc/xc_domain.c
--- a/tools/libxc/xc_domain.c   Sun Sep 18 00:26:52 2011 +0100
+++ b/tools/libxc/xc_domain.c   Thu Sep 22 18:26:54 2011 +0100
@@ -1132,13 +1132,13 @@
 int xc_assign_device(
     xc_interface *xch,
     uint32_t domid,
-    uint32_t machine_bdf)
+    uint32_t machine_sbdf)
 {
     DECLARE_DOMCTL;
 
     domctl.cmd = XEN_DOMCTL_assign_device;
     domctl.domain = domid;
-    domctl.u.assign_device.machine_bdf = machine_bdf;
+    domctl.u.assign_device.machine_sbdf = machine_sbdf;
 
     return do_domctl(xch, &domctl);
 }
@@ -1146,7 +1146,7 @@
 int xc_get_device_group(
     xc_interface *xch,
     uint32_t domid,
-    uint32_t machine_bdf,
+    uint32_t machine_sbdf,
     uint32_t max_sdevs,
     uint32_t *num_sdevs,
     uint32_t *sdev_array)
@@ -1164,7 +1164,7 @@
     domctl.cmd = XEN_DOMCTL_get_device_group;
     domctl.domain = (domid_t)domid;
 
-    domctl.u.get_device_group.machine_bdf = machine_bdf;
+    domctl.u.get_device_group.machine_sbdf = machine_sbdf;
     domctl.u.get_device_group.max_sdevs = max_sdevs;
 
     set_xen_guest_handle(domctl.u.get_device_group.sdev_array, sdev_array);
@@ -1181,13 +1181,13 @@
 int xc_test_assign_device(
     xc_interface *xch,
     uint32_t domid,
-    uint32_t machine_bdf)
+    uint32_t machine_sbdf)
 {
     DECLARE_DOMCTL;
 
     domctl.cmd = XEN_DOMCTL_test_assign_device;
     domctl.domain = domid;
-    domctl.u.assign_device.machine_bdf = machine_bdf;
+    domctl.u.assign_device.machine_sbdf = machine_sbdf;
 
     return do_domctl(xch, &domctl);
 }
@@ -1195,13 +1195,13 @@
 int xc_deassign_device(
     xc_interface *xch,
     uint32_t domid,
-    uint32_t machine_bdf)
+    uint32_t machine_sbdf)
 {
     DECLARE_DOMCTL;
 
     domctl.cmd = XEN_DOMCTL_deassign_device;
     domctl.domain = domid;
-    domctl.u.assign_device.machine_bdf = machine_bdf;
+    domctl.u.assign_device.machine_sbdf = machine_sbdf;
  
     return do_domctl(xch, &domctl);
 }
diff -r a422e2a4451e -r ec7c81fbe0de tools/libxl/libxl_pci.c
--- a/tools/libxl/libxl_pci.c   Sun Sep 18 00:26:52 2011 +0100
+++ b/tools/libxl/libxl_pci.c   Thu Sep 22 18:26:54 2011 +0100
@@ -45,10 +45,10 @@
 {
     unsigned int value;
 
-    value = 0;
-    value |= (pcidev->bus & 0xff) << 16;
-    value |= (pcidev->dev & 0x1f) << (8+3);
-    value |= (pcidev->func & 0x7) << (8+0);
+    value = pcidev->domain << 16;
+    value |= (pcidev->bus & 0xff) << 8;
+    value |= (pcidev->dev & 0x1f) << 3;
+    value |= (pcidev->func & 0x7);
 
     return value;
 }
diff -r a422e2a4451e -r ec7c81fbe0de tools/python/xen/lowlevel/xc/xc.c
--- a/tools/python/xen/lowlevel/xc/xc.c Sun Sep 18 00:26:52 2011 +0100
+++ b/tools/python/xen/lowlevel/xc/xc.c Thu Sep 22 18:26:54 2011 +0100
@@ -609,7 +609,7 @@
 {
     uint32_t dom;
     char *pci_str;
-    int32_t bdf = 0;
+    int32_t sbdf = 0;
     int seg, bus, dev, func;
 
     static char *kwd_list[] = { "domid", "pci", NULL };
@@ -619,20 +619,21 @@
 
     while ( next_bdf(&pci_str, &seg, &bus, &dev, &func) )
     {
-        bdf |= (bus & 0xff) << 16;
-        bdf |= (dev & 0x1f) << 11;
-        bdf |= (func & 0x7) << 8;
-
-        if ( xc_test_assign_device(self->xc_handle, dom, bdf) != 0 )
+        sbdf = seg << 16;
+        sbdf |= (bus & 0xff) << 8;
+        sbdf |= (dev & 0x1f) << 3;
+        sbdf |= (func & 0x7);
+
+        if ( xc_test_assign_device(self->xc_handle, dom, sbdf) != 0 )
         {
             if (errno == ENOSYS)
-                bdf = -1;
+                sbdf = -1;
             break;
         }
-        bdf = 0;
+        sbdf = 0;
     }
 
-    return Py_BuildValue("i", bdf);
+    return Py_BuildValue("i", sbdf);
 }
 
 static PyObject *pyxc_assign_device(XcObject *self,
@@ -641,7 +642,7 @@
 {
     uint32_t dom;
     char *pci_str;
-    int32_t bdf = 0;
+    int32_t sbdf = 0;
     int seg, bus, dev, func;
 
     static char *kwd_list[] = { "domid", "pci", NULL };
@@ -651,20 +652,21 @@
 
     while ( next_bdf(&pci_str, &seg, &bus, &dev, &func) )
     {
-        bdf |= (bus & 0xff) << 16;
-        bdf |= (dev & 0x1f) << 11;
-        bdf |= (func & 0x7) << 8;
-
-        if ( xc_assign_device(self->xc_handle, dom, bdf) != 0 )
+        sbdf = seg << 16;
+        sbdf |= (bus & 0xff) << 8;
+        sbdf |= (dev & 0x1f) << 3;
+        sbdf |= (func & 0x7);
+
+        if ( xc_assign_device(self->xc_handle, dom, sbdf) != 0 )
         {
             if (errno == ENOSYS)
-                bdf = -1;
+                sbdf = -1;
             break;
         }
-        bdf = 0;
+        sbdf = 0;
     }
 
-    return Py_BuildValue("i", bdf);
+    return Py_BuildValue("i", sbdf);
 }
 
 static PyObject *pyxc_deassign_device(XcObject *self,
@@ -673,7 +675,7 @@
 {
     uint32_t dom;
     char *pci_str;
-    int32_t bdf = 0;
+    int32_t sbdf = 0;
     int seg, bus, dev, func;
 
     static char *kwd_list[] = { "domid", "pci", NULL };
@@ -683,26 +685,27 @@
 
     while ( next_bdf(&pci_str, &seg, &bus, &dev, &func) )
     {
-        bdf |= (bus & 0xff) << 16;
-        bdf |= (dev & 0x1f) << 11;
-        bdf |= (func & 0x7) << 8;
-
-        if ( xc_deassign_device(self->xc_handle, dom, bdf) != 0 )
+        sbdf = seg << 16;
+        sbdf |= (bus & 0xff) << 8;
+        sbdf |= (dev & 0x1f) << 3;
+        sbdf |= (func & 0x7);
+
+        if ( xc_deassign_device(self->xc_handle, dom, sbdf) != 0 )
         {
             if (errno == ENOSYS)
-                bdf = -1;
+                sbdf = -1;
             break;
         }
-        bdf = 0;
+        sbdf = 0;
     }
 
-    return Py_BuildValue("i", bdf);
+    return Py_BuildValue("i", sbdf);
 }
 
 static PyObject *pyxc_get_device_group(XcObject *self,
                                          PyObject *args)
 {
-    uint32_t bdf = 0;
+    uint32_t sbdf;
     uint32_t max_sdevs, num_sdevs;
     int domid, seg, bus, dev, func, rc, i;
     PyObject *Pystr;
@@ -720,12 +723,13 @@
     if (sdev_array == NULL)
         return PyErr_NoMemory();
 
-    bdf |= (bus & 0xff) << 16;
-    bdf |= (dev & 0x1f) << 11;
-    bdf |= (func & 0x7) << 8;
+    sbdf = seg << 16;
+    sbdf |= (bus & 0xff) << 8;
+    sbdf |= (dev & 0x1f) << 3;
+    sbdf |= (func & 0x7);
 
     rc = xc_get_device_group(self->xc_handle,
-        domid, bdf, max_sdevs, &num_sdevs, sdev_array);
+        domid, sbdf, max_sdevs, &num_sdevs, sdev_array);
 
     if ( rc < 0 )
     {
diff -r a422e2a4451e -r ec7c81fbe0de xen/arch/ia64/xen/dom0_ops.c
--- a/xen/arch/ia64/xen/dom0_ops.c      Sun Sep 18 00:26:52 2011 +0100
+++ b/xen/arch/ia64/xen/dom0_ops.c      Thu Sep 22 18:26:54 2011 +0100
@@ -258,138 +258,6 @@
     }
     break;
 
-    case XEN_DOMCTL_get_device_group:
-    {
-        struct domain *d;
-        u32 max_sdevs;
-        u8 bus, devfn;
-        XEN_GUEST_HANDLE_64(uint32) sdevs;
-        int num_sdevs;
-
-        ret = -ENOSYS;
-        if ( !iommu_enabled )
-            break;
-
-        ret = -EINVAL;
-        if ( (d = rcu_lock_domain_by_id(op->domain)) == NULL )
-            break;
-
-        bus = (op->u.get_device_group.machine_bdf >> 16) & 0xff;
-        devfn = (op->u.get_device_group.machine_bdf >> 8) & 0xff;
-        max_sdevs = op->u.get_device_group.max_sdevs;
-        sdevs = op->u.get_device_group.sdev_array;
-
-        num_sdevs = iommu_get_device_group(d, bus, devfn, sdevs, max_sdevs);
-        if ( num_sdevs < 0 )
-        {
-            dprintk(XENLOG_ERR, "iommu_get_device_group() failed!\n");
-            ret = -EFAULT;
-            op->u.get_device_group.num_sdevs = 0;
-        }
-        else
-        {
-            ret = 0;
-            op->u.get_device_group.num_sdevs = num_sdevs;
-        }
-        if ( copy_to_guest(u_domctl, op, 1) )
-            ret = -EFAULT;
-        rcu_unlock_domain(d);
-    }
-    break;
-
-    case XEN_DOMCTL_test_assign_device:
-    {
-        u8 bus, devfn;
-
-        ret = -ENOSYS;
-        if ( !iommu_enabled )
-            break;
-
-        ret = -EINVAL;
-        bus = (op->u.assign_device.machine_bdf >> 16) & 0xff;
-        devfn = (op->u.assign_device.machine_bdf >> 8) & 0xff;
-
-        if ( device_assigned(bus, devfn) )
-        {
-            printk( "XEN_DOMCTL_test_assign_device: "
-                     "%x:%x.%x already assigned, or non-existent\n",
-                     bus, PCI_SLOT(devfn), PCI_FUNC(devfn));
-            break;
-        }
-        ret = 0;
-    }
-    break;
-
-    case XEN_DOMCTL_assign_device:
-    {
-        struct domain *d;
-        u8 bus, devfn;
-
-        ret = -ENOSYS;
-        if ( !iommu_enabled )
-            break;
-
-        ret = -EINVAL;
-        if ( unlikely((d = get_domain_by_id(op->domain)) == NULL) )
-        {
-            gdprintk(XENLOG_ERR,
-                "XEN_DOMCTL_assign_device: get_domain_by_id() failed\n");
-            break;
-        }
-        bus = (op->u.assign_device.machine_bdf >> 16) & 0xff;
-        devfn = (op->u.assign_device.machine_bdf >> 8) & 0xff;
-
-        if ( device_assigned(bus, devfn) )
-        {
-            gdprintk(XENLOG_ERR, "XEN_DOMCTL_assign_device: "
-                     "%x:%x.%x already assigned, or non-existent\n",
-                     bus, PCI_SLOT(devfn), PCI_FUNC(devfn));
-            break;
-        }
-
-        ret = assign_device(d, bus, devfn);
-        if ( ret )
-            gdprintk(XENLOG_ERR, "XEN_DOMCTL_assign_device: "
-                     "assign device (%x:%x.%x) failed\n",
-                     bus, PCI_SLOT(devfn), PCI_FUNC(devfn));
-        put_domain(d);
-    }
-    break;
-
-    case XEN_DOMCTL_deassign_device:
-    {
-        struct domain *d;
-        u8 bus, devfn;
-
-        ret = -ENOSYS;
-        if ( !iommu_enabled )
-            break;
-
-        ret = -EINVAL;
-        if ( unlikely((d = get_domain_by_id(op->domain)) == NULL) )
-        {
-            gdprintk(XENLOG_ERR,
-                "XEN_DOMCTL_deassign_device: get_domain_by_id() failed\n");
-            break;
-        }
-        bus = (op->u.assign_device.machine_bdf >> 16) & 0xff;
-        devfn = (op->u.assign_device.machine_bdf >> 8) & 0xff;
-
-        if ( !device_assigned(bus, devfn) )
-            break;
-
-        spin_lock(&pcidevs_lock);
-        ret = deassign_device(d, bus, devfn);
-        spin_unlock(&pcidevs_lock);
-        if ( ret )
-            gdprintk(XENLOG_ERR, "XEN_DOMCTL_deassign_device: "
-                     "deassign device (%x:%x.%x) failed\n",
-                     bus, PCI_SLOT(devfn), PCI_FUNC(devfn));
-
-        put_domain(d);
-    }
-    break;
-
     case XEN_DOMCTL_bind_pt_irq:
     {
         struct domain * d;
@@ -707,8 +575,8 @@
     break;
 
     default:
-        printk("arch_do_domctl: unrecognized domctl: %d!!!\n",op->cmd);
-        ret = -ENOSYS;
+        ret = iommu_do_domctl(op, u_domctl);
+        break;
 
     }
 
diff -r a422e2a4451e -r ec7c81fbe0de xen/arch/x86/domctl.c
--- a/xen/arch/x86/domctl.c     Sun Sep 18 00:26:52 2011 +0100
+++ b/xen/arch/x86/domctl.c     Thu Sep 22 18:26:54 2011 +0100
@@ -742,144 +742,6 @@
     }
     break;
 
-    case XEN_DOMCTL_get_device_group:
-    {
-        struct domain *d;
-        u32 max_sdevs;
-        u8 bus, devfn;
-        XEN_GUEST_HANDLE_64(uint32) sdevs;
-        int num_sdevs;
-
-        ret = -ENOSYS;
-        if ( !iommu_enabled )
-            break;
-
-        ret = -EINVAL;
-        if ( (d = rcu_lock_domain_by_id(domctl->domain)) == NULL )
-            break;
-
-        bus = (domctl->u.get_device_group.machine_bdf >> 16) & 0xff;
-        devfn = (domctl->u.get_device_group.machine_bdf >> 8) & 0xff;
-        max_sdevs = domctl->u.get_device_group.max_sdevs;
-        sdevs = domctl->u.get_device_group.sdev_array;
-
-        num_sdevs = iommu_get_device_group(d, bus, devfn, sdevs, max_sdevs);
-        if ( num_sdevs < 0 )
-        {
-            dprintk(XENLOG_ERR, "iommu_get_device_group() failed!\n");
-            ret = -EFAULT;
-            domctl->u.get_device_group.num_sdevs = 0;
-        }
-        else
-        {
-            ret = 0;
-            domctl->u.get_device_group.num_sdevs = num_sdevs;
-        }
-        if ( copy_to_guest(u_domctl, domctl, 1) )
-            ret = -EFAULT;
-        rcu_unlock_domain(d);
-    }
-    break;
-
-    case XEN_DOMCTL_test_assign_device:
-    {
-        u8 bus, devfn;
-
-        ret = -ENOSYS;
-        if ( !iommu_enabled )
-            break;
-
-        ret = xsm_test_assign_device(domctl->u.assign_device.machine_bdf);
-        if ( ret )
-            break;
-
-        ret = -EINVAL;
-        bus = (domctl->u.assign_device.machine_bdf >> 16) & 0xff;
-        devfn = (domctl->u.assign_device.machine_bdf >> 8) & 0xff;
-
-        if ( device_assigned(bus, devfn) )
-        {
-            gdprintk(XENLOG_ERR, "XEN_DOMCTL_test_assign_device: "
-                     "%x:%x.%x already assigned, or non-existent\n",
-                     bus, PCI_SLOT(devfn), PCI_FUNC(devfn));
-            break;
-        }
-        ret = 0;
-    }
-    break;
-
-    case XEN_DOMCTL_assign_device:
-    {
-        struct domain *d;
-        u8 bus, devfn;
-
-        ret = -ENOSYS;
-        if ( !iommu_enabled )
-            break;
-
-        ret = -EINVAL;
-        if ( unlikely((d = get_domain_by_id(domctl->domain)) == NULL) )
-        {
-            gdprintk(XENLOG_ERR,
-                "XEN_DOMCTL_assign_device: get_domain_by_id() failed\n");
-            break;
-        }
-
-        ret = xsm_assign_device(d, domctl->u.assign_device.machine_bdf);
-        if ( ret )
-            goto assign_device_out;
-
-        bus = (domctl->u.assign_device.machine_bdf >> 16) & 0xff;
-        devfn = (domctl->u.assign_device.machine_bdf >> 8) & 0xff;
-
-        ret = assign_device(d, bus, devfn);
-        if ( ret )
-            gdprintk(XENLOG_ERR, "XEN_DOMCTL_assign_device: "
-                     "assign device (%x:%x.%x) failed\n",
-                     bus, PCI_SLOT(devfn), PCI_FUNC(devfn));
-
-    assign_device_out:
-        put_domain(d);
-    }
-    break;
-
-    case XEN_DOMCTL_deassign_device:
-    {
-        struct domain *d;
-        u8 bus, devfn;
-
-        ret = -ENOSYS;
-        if ( !iommu_enabled )
-            break;
-
-        ret = -EINVAL;
-        if ( unlikely((d = get_domain_by_id(domctl->domain)) == NULL) )
-        {
-            gdprintk(XENLOG_ERR,
-                "XEN_DOMCTL_deassign_device: get_domain_by_id() failed\n");
-            break;
-        }
-
-        ret = xsm_assign_device(d, domctl->u.assign_device.machine_bdf);
-        if ( ret )
-            goto deassign_device_out;
-
-        bus = (domctl->u.assign_device.machine_bdf >> 16) & 0xff;
-        devfn = (domctl->u.assign_device.machine_bdf >> 8) & 0xff;
-
-        spin_lock(&pcidevs_lock);
-        ret = deassign_device(d, bus, devfn);
-        spin_unlock(&pcidevs_lock);
-        if ( ret )
-            gdprintk(XENLOG_ERR, "XEN_DOMCTL_deassign_device: "
-                     "deassign device (%x:%x.%x) failed\n",
-                     bus, PCI_SLOT(devfn), PCI_FUNC(devfn));
-
-    deassign_device_out:
-        put_domain(d);
-    }
-    break;
-
     case XEN_DOMCTL_bind_pt_irq:
     {
         struct domain * d;
@@ -1601,7 +1463,7 @@
     break;
 
     default:
-        ret = -ENOSYS;
+        ret = iommu_do_domctl(domctl, u_domctl);
         break;
     }
 
diff -r a422e2a4451e -r ec7c81fbe0de xen/drivers/passthrough/amd/pci_amd_iommu.c
--- a/xen/drivers/passthrough/amd/pci_amd_iommu.c       Sun Sep 18 00:26:52 
2011 +0100
+++ b/xen/drivers/passthrough/amd/pci_amd_iommu.c       Thu Sep 22 18:26:54 
2011 +0100
@@ -305,7 +305,7 @@
 }
 
 static int reassign_device( struct domain *source, struct domain *target,
-                            u8 bus, u8 devfn)
+                            u16 seg, u8 bus, u8 devfn)
 {
     struct pci_dev *pdev;
     struct amd_iommu *iommu;
@@ -313,7 +313,7 @@
     struct hvm_iommu *t = domain_hvm_iommu(target);
 
     ASSERT(spin_is_locked(&pcidevs_lock));
-    pdev = pci_get_pdev_by_domain(source, 0, bus, devfn);
+    pdev = pci_get_pdev_by_domain(source, seg, bus, devfn);
     if ( !pdev )
         return -ENODEV;
 
@@ -346,7 +346,7 @@
     return 0;
 }
 
-static int amd_iommu_assign_device(struct domain *d, u8 bus, u8 devfn)
+static int amd_iommu_assign_device(struct domain *d, u16 seg, u8 bus, u8 devfn)
 {
     int bdf = (bus << 8) | devfn;
     int req_id = get_dma_requestor_id(bdf);
@@ -361,7 +361,7 @@
             ivrs_mappings[req_id].read_permission);
     }
 
-    return reassign_device(dom0, d, bus, devfn);
+    return reassign_device(dom0, d, seg, bus, devfn);
 }
 
 static void deallocate_next_page_table(struct page_info* pg, int level)
@@ -426,9 +426,9 @@
 }
 
 static int amd_iommu_return_device(
-    struct domain *s, struct domain *t, u8 bus, u8 devfn)
+    struct domain *s, struct domain *t, u16 seg, u8 bus, u8 devfn)
 {
-    return reassign_device(s, t, bus, devfn);
+    return reassign_device(s, t, seg, bus, devfn);
 }
 
 static int amd_iommu_add_device(struct pci_dev *pdev)
@@ -475,7 +475,7 @@
     return 0;
 }
 
-static int amd_iommu_group_id(u8 bus, u8 devfn)
+static int amd_iommu_group_id(u16 seg, u8 bus, u8 devfn)
 {
     int rt;
     int bdf = (bus << 8) | devfn;
diff -r a422e2a4451e -r ec7c81fbe0de xen/drivers/passthrough/iommu.c
--- a/xen/drivers/passthrough/iommu.c   Sun Sep 18 00:26:52 2011 +0100
+++ b/xen/drivers/passthrough/iommu.c   Thu Sep 22 18:26:54 2011 +0100
@@ -19,6 +19,7 @@
 #include <xen/paging.h>
 #include <xen/guest_access.h>
 #include <xen/softirq.h>
+#include <xsm/xsm.h>
 
 static void parse_iommu_param(char *s);
 static int iommu_populate_page_table(struct domain *d);
@@ -165,7 +166,22 @@
     return hd->platform_ops->remove_device(pdev);
 }
 
-int assign_device(struct domain *d, u8 bus, u8 devfn)
+/*
+ * If the device isn't owned by dom0, it means it already
+ * has been assigned to other domain, or it doesn't exist.
+ */
+static int device_assigned(u16 seg, u8 bus, u8 devfn)
+{
+    struct pci_dev *pdev;
+
+    spin_lock(&pcidevs_lock);
+    pdev = pci_get_pdev_by_domain(dom0, seg, bus, devfn);
+    spin_unlock(&pcidevs_lock);
+
+    return pdev ? 0 : -1;
+}
+
+static int assign_device(struct domain *d, u16 seg, u8 bus, u8 devfn)
 {
     struct hvm_iommu *hd = domain_hvm_iommu(d);
     int rc = 0;
@@ -174,7 +190,7 @@
         return 0;
 
     spin_lock(&pcidevs_lock);
-    if ( (rc = hd->platform_ops->assign_device(d, bus, devfn)) )
+    if ( (rc = hd->platform_ops->assign_device(d, seg, bus, devfn)) )
         goto done;
 
     if ( has_arch_pdevs(d) && !need_iommu(d) )
@@ -272,7 +288,7 @@
 }
 
 /* caller should hold the pcidevs_lock */
-int deassign_device(struct domain *d, u8 bus, u8 devfn)
+int deassign_device(struct domain *d, u16 seg, u8 bus, u8 devfn)
 {
     struct hvm_iommu *hd = domain_hvm_iommu(d);
     struct pci_dev *pdev = NULL;
@@ -282,7 +298,7 @@
         return -EINVAL;
 
     ASSERT(spin_is_locked(&pcidevs_lock));
-    pdev = pci_get_pdev(0, bus, devfn);
+    pdev = pci_get_pdev(seg, bus, devfn);
     if ( !pdev )
         return -ENODEV;
 
@@ -293,12 +309,12 @@
         return -EINVAL;
     }
 
-    ret = hd->platform_ops->reassign_device(d, dom0, bus, devfn);
+    ret = hd->platform_ops->reassign_device(d, dom0, seg, bus, devfn);
     if ( ret )
     {
         dprintk(XENLOG_ERR VTDPREFIX,
-                "d%d: Deassign device (%x:%x.%x) failed!\n",
-                d->domain_id, bus, PCI_SLOT(devfn), PCI_FUNC(devfn));
+                "d%d: Deassign device (%04x:%02x:%02x.%u) failed!\n",
+                d->domain_id, seg, bus, PCI_SLOT(devfn), PCI_FUNC(devfn));
         return ret;
     }
 
@@ -347,7 +363,8 @@
     return rc;
 }
 
-int iommu_get_device_group(struct domain *d, u8 bus, u8 devfn, 
+static int iommu_get_device_group(
+    struct domain *d, u16 seg, u8 bus, u8 devfn,
     XEN_GUEST_HANDLE_64(uint32) buf, int max_sdevs)
 {
     struct hvm_iommu *hd = domain_hvm_iommu(d);
@@ -360,15 +377,16 @@
     if ( !iommu_enabled || !ops || !ops->get_device_group_id )
         return 0;
 
-    group_id = ops->get_device_group_id(bus, devfn);
+    group_id = ops->get_device_group_id(seg, bus, devfn);
 
     spin_lock(&pcidevs_lock);
     for_each_pdev( d, pdev )
     {
-        if ( (pdev->bus == bus) && (pdev->devfn == devfn) )
+        if ( (pdev->seg != seg) ||
+             ((pdev->bus == bus) && (pdev->devfn == devfn)) )
             continue;
 
-        sdev_id = ops->get_device_group_id(pdev->bus, pdev->devfn);
+        sdev_id = ops->get_device_group_id(seg, pdev->bus, pdev->devfn);
         if ( (sdev_id == group_id) && (i < max_sdevs) )
         {
             bdf = 0;
@@ -443,6 +461,154 @@
     iommu_enabled = 0;
 }
 
+int iommu_do_domctl(
+    struct xen_domctl *domctl,
+    XEN_GUEST_HANDLE(xen_domctl_t) u_domctl)
+{
+    struct domain *d;
+    u16 seg;
+    u8 bus, devfn;
+    int ret = 0;
+
+    if ( !iommu_enabled )
+        return -ENOSYS;
+
+    switch ( domctl->cmd )
+    {
+    case XEN_DOMCTL_get_device_group:
+    {
+        u32 max_sdevs;
+        XEN_GUEST_HANDLE_64(uint32) sdevs;
+
+        ret = -EINVAL;
+        if ( (d = rcu_lock_domain_by_id(domctl->domain)) == NULL )
+            break;
+
+        seg = domctl->u.get_device_group.machine_sbdf >> 16;
+        bus = (domctl->u.get_device_group.machine_sbdf >> 8) & 0xff;
+        devfn = domctl->u.get_device_group.machine_sbdf & 0xff;
+        max_sdevs = domctl->u.get_device_group.max_sdevs;
+        sdevs = domctl->u.get_device_group.sdev_array;
+
+        ret = iommu_get_device_group(d, seg, bus, devfn, sdevs, max_sdevs);
+        if ( ret < 0 )
+        {
+            dprintk(XENLOG_ERR, "iommu_get_device_group() failed!\n");
+            ret = -EFAULT;
+            domctl->u.get_device_group.num_sdevs = 0;
+        }
+        else
+        {
+            domctl->u.get_device_group.num_sdevs = ret;
+            ret = 0;
+        }
+        if ( copy_to_guest(u_domctl, domctl, 1) )
+            ret = -EFAULT;
+        rcu_unlock_domain(d);
+    }
+    break;
+
+    case XEN_DOMCTL_test_assign_device:
+        ret = xsm_test_assign_device(domctl->u.assign_device.machine_sbdf);
+        if ( ret )
+            break;
+
+        seg = domctl->u.get_device_group.machine_sbdf >> 16;
+        bus = (domctl->u.assign_device.machine_sbdf >> 8) & 0xff;
+        devfn = domctl->u.assign_device.machine_sbdf & 0xff;
+
+        if ( device_assigned(seg, bus, devfn) )
+        {
+            gdprintk(XENLOG_ERR, "XEN_DOMCTL_test_assign_device: "
+                     "%04x:%02x:%02x.%u already assigned, or non-existent\n",
+                     seg, bus, PCI_SLOT(devfn), PCI_FUNC(devfn));
+            ret = -EINVAL;
+        }
+        break;
+
+    case XEN_DOMCTL_assign_device:
+        if ( unlikely((d = get_domain_by_id(domctl->domain)) == NULL) )
+        {
+            gdprintk(XENLOG_ERR,
+                "XEN_DOMCTL_assign_device: get_domain_by_id() failed\n");
+            ret = -EINVAL;
+            break;
+        }
+
+        ret = xsm_assign_device(d, domctl->u.assign_device.machine_sbdf);
+        if ( ret )
+            goto assign_device_out;
+
+        seg = domctl->u.get_device_group.machine_sbdf >> 16;
+        bus = (domctl->u.assign_device.machine_sbdf >> 8) & 0xff;
+        devfn = domctl->u.assign_device.machine_sbdf & 0xff;
+
+#ifdef __ia64__ /* XXX Is this really needed? */
+        if ( device_assigned(seg, bus, devfn) )
+        {
+            gdprintk(XENLOG_ERR, "XEN_DOMCTL_assign_device: "
+                     "%x:%x.%x already assigned, or non-existent\n",
+                     bus, PCI_SLOT(devfn), PCI_FUNC(devfn));
+            ret = -EINVAL;
+            goto assign_device_out;
+        }
+#endif
+
+        ret = assign_device(d, seg, bus, devfn);
+        if ( ret )
+            gdprintk(XENLOG_ERR, "XEN_DOMCTL_assign_device: "
+                     "assign device (%04x:%02x:%02x.%u) failed\n",
+                     seg, bus, PCI_SLOT(devfn), PCI_FUNC(devfn));
+
+    assign_device_out:
+        put_domain(d);
+        break;
+
+    case XEN_DOMCTL_deassign_device:
+        if ( unlikely((d = get_domain_by_id(domctl->domain)) == NULL) )
+        {
+            gdprintk(XENLOG_ERR,
+                "XEN_DOMCTL_deassign_device: get_domain_by_id() failed\n");
+            ret = -EINVAL;
+            break;
+        }
+
+        ret = xsm_assign_device(d, domctl->u.assign_device.machine_sbdf);
+        if ( ret )
+            goto deassign_device_out;
+
+        seg = domctl->u.get_device_group.machine_sbdf >> 16;
+        bus = (domctl->u.assign_device.machine_sbdf >> 8) & 0xff;
+        devfn = domctl->u.assign_device.machine_sbdf & 0xff;
+
+#ifdef __ia64__ /* XXX Is this really needed? */
+        if ( !device_assigned(seg, bus, devfn) )
+        {
+            ret = -EINVAL;
+            goto deassign_device_out;
+        }
+#endif
+
+        spin_lock(&pcidevs_lock);
+        ret = deassign_device(d, seg, bus, devfn);
+        spin_unlock(&pcidevs_lock);
+        if ( ret )
+            gdprintk(XENLOG_ERR, "XEN_DOMCTL_deassign_device: "
+                     "deassign device (%04x:%02x:%02x.%u) failed\n",
+                     seg, bus, PCI_SLOT(devfn), PCI_FUNC(devfn));
+
+    deassign_device_out:
+        put_domain(d);
+        break;
+
+    default:
+        ret = -ENOSYS;
+        break;
+    }
+
+    return ret;
+}
+
 /*
  * Local variables:
  * mode: C
diff -r a422e2a4451e -r ec7c81fbe0de xen/drivers/passthrough/pci.c
--- a/xen/drivers/passthrough/pci.c     Sun Sep 18 00:26:52 2011 +0100
+++ b/xen/drivers/passthrough/pci.c     Thu Sep 22 18:26:54 2011 +0100
@@ -441,11 +441,12 @@
     while ( (pdev = pci_get_pdev_by_domain(d, -1, -1, -1)) )
     {
         pci_cleanup_msi(pdev);
-        bus = pdev->bus; devfn = pdev->devfn;
-        if ( deassign_device(d, bus, devfn) )
-            printk("domain %d: deassign device (%02x:%02x.%x) failed!\n",
-                   d->domain_id, pdev->bus, PCI_SLOT(pdev->devfn),
-                   PCI_FUNC(pdev->devfn));
+        bus = pdev->bus;
+        devfn = pdev->devfn;
+        if ( deassign_device(d, pdev->seg, bus, devfn) )
+            printk("domain %d: deassign device (%04x:%02x:%02x.%u) failed!\n",
+                   d->domain_id, pdev->seg, bus,
+                   PCI_SLOT(devfn), PCI_FUNC(devfn));
     }
     spin_unlock(&pcidevs_lock);
 }
diff -r a422e2a4451e -r ec7c81fbe0de xen/drivers/passthrough/vtd/iommu.c
--- a/xen/drivers/passthrough/vtd/iommu.c       Sun Sep 18 00:26:52 2011 +0100
+++ b/xen/drivers/passthrough/vtd/iommu.c       Thu Sep 22 18:26:54 2011 +0100
@@ -1620,13 +1620,13 @@
 static int reassign_device_ownership(
     struct domain *source,
     struct domain *target,
-    u8 bus, u8 devfn)
+    u16 seg, u8 bus, u8 devfn)
 {
     struct pci_dev *pdev;
     int ret;
 
     ASSERT(spin_is_locked(&pcidevs_lock));
-    pdev = pci_get_pdev_by_domain(source, 0, bus, devfn);
+    pdev = pci_get_pdev_by_domain(source, seg, bus, devfn);
 
     if (!pdev)
         return -ENODEV;
@@ -2153,27 +2153,8 @@
     return ret;
 }
 
-/*
- * If the device isn't owned by dom0, it means it already
- * has been assigned to other domain, or it's not exist.
- */
-int device_assigned(u8 bus, u8 devfn)
-{
-    struct pci_dev *pdev;
-
-    spin_lock(&pcidevs_lock);
-    pdev = pci_get_pdev_by_domain(dom0, 0, bus, devfn);
-    if (!pdev)
-    {
-        spin_unlock(&pcidevs_lock);
-        return -1;
-    }
-
-    spin_unlock(&pcidevs_lock);
-    return 0;
-}
-
-static int intel_iommu_assign_device(struct domain *d, u8 bus, u8 devfn)
+static int intel_iommu_assign_device(
+    struct domain *d, u16 seg, u8 bus, u8 devfn)
 {
     struct acpi_rmrr_unit *rmrr;
     int ret = 0, i;
@@ -2184,7 +2165,7 @@
         return -ENODEV;
 
     ASSERT(spin_is_locked(&pcidevs_lock));
-    pdev = pci_get_pdev(0, bus, devfn);
+    pdev = pci_get_pdev(seg, bus, devfn);
     if (!pdev)
         return -ENODEV;
 
@@ -2195,7 +2176,7 @@
        return -EBUSY;
     }
 
-    ret = reassign_device_ownership(dom0, d, bus, devfn);
+    ret = reassign_device_ownership(dom0, d, seg, bus, devfn);
     if ( ret )
         goto done;
 
@@ -2227,7 +2208,7 @@
     return ret;
 }
 
-static int intel_iommu_group_id(u8 bus, u8 devfn)
+static int intel_iommu_group_id(u16 seg, u8 bus, u8 devfn)
 {
     u8 secbus;
     if ( find_upstream_bridge(&bus, &devfn, &secbus) < 0 )
diff -r a422e2a4451e -r ec7c81fbe0de xen/include/public/domctl.h
--- a/xen/include/public/domctl.h       Sun Sep 18 00:26:52 2011 +0100
+++ b/xen/include/public/domctl.h       Thu Sep 22 18:26:54 2011 +0100
@@ -455,15 +455,15 @@
 /* XEN_DOMCTL_test_assign_device */
 /* XEN_DOMCTL_deassign_device */
 struct xen_domctl_assign_device {
-    uint32_t  machine_bdf;   /* machine PCI ID of assigned device */
+    uint32_t  machine_sbdf;   /* machine PCI ID of assigned device */
 };
 typedef struct xen_domctl_assign_device xen_domctl_assign_device_t;
 DEFINE_XEN_GUEST_HANDLE(xen_domctl_assign_device_t);
 
-/* Retrieve sibling devices infomation of machine_bdf */
+/* Retrieve sibling devices infomation of machine_sbdf */
 /* XEN_DOMCTL_get_device_group */
 struct xen_domctl_get_device_group {
-    uint32_t  machine_bdf;      /* IN */
+    uint32_t  machine_sbdf;     /* IN */
     uint32_t  max_sdevs;        /* IN */
     uint32_t  num_sdevs;        /* OUT */
     XEN_GUEST_HANDLE_64(uint32)  sdev_array;   /* OUT */
diff -r a422e2a4451e -r ec7c81fbe0de xen/include/xen/iommu.h
--- a/xen/include/xen/iommu.h   Sun Sep 18 00:26:52 2011 +0100
+++ b/xen/include/xen/iommu.h   Thu Sep 22 18:26:54 2011 +0100
@@ -74,11 +74,7 @@
 int iommu_domain_init(struct domain *d);
 void iommu_dom0_init(struct domain *d);
 void iommu_domain_destroy(struct domain *d);
-int device_assigned(u8 bus, u8 devfn);
-int assign_device(struct domain *d, u8 bus, u8 devfn);
-int deassign_device(struct domain *d, u8 bus, u8 devfn);
-int iommu_get_device_group(struct domain *d, u8 bus, u8 devfn,
-    XEN_GUEST_HANDLE_64(uint32) buf, int max_sdevs);
+int deassign_device(struct domain *d, u16 seg, u8 bus, u8 devfn);
 
 /* iommu_map_page() takes flags to direct the mapping operation. */
 #define _IOMMUF_readable 0
@@ -125,14 +121,14 @@
     void (*dom0_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);
+    int (*assign_device)(struct domain *d, u16 seg, u8 bus, u8 devfn);
     void (*teardown)(struct domain *d);
     int (*map_page)(struct domain *d, unsigned long gfn, unsigned long mfn,
                     unsigned int flags);
     int (*unmap_page)(struct domain *d, unsigned long gfn);
     int (*reassign_device)(struct domain *s, struct domain *t,
-                          u8 bus, u8 devfn);
-    int (*get_device_group_id)(u8 bus, u8 devfn);
+                          u16 seg, u8 bus, u8 devfn);
+    int (*get_device_group_id)(u16 seg, u8 bus, u8 devfn);
     void (*update_ire_from_apic)(unsigned int apic, unsigned int reg, unsigned 
int value);
     void (*update_ire_from_msi)(struct msi_desc *msi_desc, struct msi_msg 
*msg);
     void (*read_msi_from_ire)(struct msi_desc *msi_desc, struct msi_msg *msg);
@@ -155,4 +151,6 @@
 void iommu_set_dom0_mapping(struct domain *d);
 void iommu_share_p2m_table(struct domain *d);
 
+int iommu_do_domctl(struct xen_domctl *, XEN_GUEST_HANDLE(xen_domctl_t));
+
 #endif /* _IOMMU_H_ */

_______________________________________________
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] PCI multi-seg: adjust domctl interface, Xen patchbot-unstable <=