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

Re: [Xen-devel] [PATCH 3/7] PCI multi-seg: adjust domctl interface

To: Jan Beulich <JBeulich@xxxxxxxx>, "xen-devel@xxxxxxxxxxxxxxxxxxx" <xen-devel@xxxxxxxxxxxxxxxxxxx>, Ian Jackson <Ian.Jackson@xxxxxxxxxxxxx>
Subject: Re: [Xen-devel] [PATCH 3/7] PCI multi-seg: adjust domctl interface
From: Keir Fraser <keir.xen@xxxxxxxxx>
Date: Wed, 21 Sep 2011 05:37:03 -0700
Cc:
Delivery-date: Wed, 21 Sep 2011 05:38:09 -0700
Dkim-signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=user-agent:date:subject:from:to:message-id:thread-topic :thread-index:in-reply-to:mime-version:content-type :content-transfer-encoding; bh=mAFsKbzV/UYBxry8MfBd5IMnMv6yzar2lQpluUsG3Gw=; b=WmAmAfC5JskkXr8E6nrtd+S+xo/dRkd/CjZj7kioPgkKi061mfvP2F2mwqdU8SDbPX 2I0ul+4Cxq2MmqrebedHnLIADqvQ4WTC4LfAxRDODyxBug+roKwFXHpfcZx1KaBwboqo PEVgOuJ2RLuCbmnIfppK8kSKWS43ZU4aGw+Yg=
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
In-reply-to: <4E78CAD60200007800056D24@xxxxxxxxxxxxxxxxxxxx>
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>
Sender: xen-devel-bounces@xxxxxxxxxxxxxxxxxxx
Thread-index: Acx4WyoQgZ5KO3pYwEWcZtG2CDyqyA==
Thread-topic: [Xen-devel] [PATCH 3/7] PCI multi-seg: adjust domctl interface
User-agent: Microsoft-Entourage/12.30.0.110427
On 20/09/2011 08:18, "Jan Beulich" <JBeulich@xxxxxxxx> wrote:

> Again, a couple of directly related functions at once get adjusted to
> account for the segment number.
> 
> Do we need to bump XEN_DOMCTL_INTERFACE_VERSION for the changes to the
> domctl interface (namely the renaming and bit-reassigment of the
> machine_bdf member of two of the interface structures)? If so, this
> can probably be done as the patch gets checked in (rather than me
> having to re-submit)?

Ian suggests we should keep compatibility with old qemu versions. Are any of
these hypercall commands used by qemu?

 -- Keir

> Signed-off-by: Jan Beulich <jbeulich@xxxxxxxx>
> 
> --- 2011-09-20.orig/tools/libxc/xc_domain.c 2011-06-16 09:21:02.000000000
> +0200
> +++ 2011-09-20/tools/libxc/xc_domain.c 2011-09-15 16:51:12.000000000 +0200
> @@ -1132,13 +1132,13 @@ int xc_domain_setdebugging(xc_interface
>  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_assign_device(
>  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 @@ int xc_get_device_group(
>      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_get_device_group(
>  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_test_assign_device(
>  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);
>  }
> --- 2011-09-20.orig/tools/libxl/libxl_pci.c 2011-09-05 09:12:30.000000000
> +0200
> +++ 2011-09-20/tools/libxl/libxl_pci.c 2011-09-15 15:40:28.000000000 +0200
> @@ -45,10 +45,10 @@ static unsigned int pcidev_encode_bdf(li
>  {
>      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;
>  }
> --- 2011-09-20.orig/tools/python/xen/lowlevel/xc/xc.c 2010-11-05
> 09:22:58.000000000 +0100
> +++ 2011-09-20/tools/python/xen/lowlevel/xc/xc.c 2011-09-15 15:48:10.000000000
> +0200
> @@ -609,7 +609,7 @@ static PyObject *pyxc_test_assign_device
>  {
>      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 @@ static PyObject *pyxc_test_assign_device
>  
>      while ( next_bdf(&pci_str, &seg, &bus, &dev, &func) )
>      {
> -        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);
>  
> -        if ( xc_test_assign_device(self->xc_handle, dom, bdf) != 0 )
> +        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 @@ static PyObject *pyxc_assign_device(XcOb
>  {
>      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 @@ static PyObject *pyxc_assign_device(XcOb
>  
>      while ( next_bdf(&pci_str, &seg, &bus, &dev, &func) )
>      {
> -        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);
>  
> -        if ( xc_assign_device(self->xc_handle, dom, bdf) != 0 )
> +        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 @@ static PyObject *pyxc_deassign_device(Xc
>  {
>      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 @@ static PyObject *pyxc_deassign_device(Xc
>  
>      while ( next_bdf(&pci_str, &seg, &bus, &dev, &func) )
>      {
> -        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);
>  
> -        if ( xc_deassign_device(self->xc_handle, dom, bdf) != 0 )
> +        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 @@ static PyObject *pyxc_get_device_group(X
>      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 )
>      {
> --- 2011-09-20.orig/xen/arch/ia64/xen/dom0_ops.c 2011-09-19 10:58:18.000000000
> +0200
> +++ 2011-09-20/xen/arch/ia64/xen/dom0_ops.c 2011-09-15 16:32:59.000000000
> +0200
> @@ -258,138 +258,6 @@ long arch_do_domctl(xen_domctl_t *op, XE
>      }
>      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 @@ long arch_do_domctl(xen_domctl_t *op, XE
>      break;
>  
>      default:
> -        printk("arch_do_domctl: unrecognized domctl: %d!!!\n",op->cmd);
> -        ret = -ENOSYS;
> +        ret = iommu_do_domctl(op, u_domctl);
> +        break;
>  
>      }
>  
> --- 2011-09-20.orig/xen/arch/x86/domctl.c 2011-06-16 09:21:02.000000000 +0200
> +++ 2011-09-20/xen/arch/x86/domctl.c 2011-09-15 16:09:39.000000000 +0200
> @@ -742,144 +742,6 @@ long arch_do_domctl(
>      }
>      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 @@ long arch_do_domctl(
>      break;
>  
>      default:
> -        ret = -ENOSYS;
> +        ret = iommu_do_domctl(domctl, u_domctl);
>          break;
>      }
>  
> --- 2011-09-20.orig/xen/drivers/passthrough/amd/pci_amd_iommu.c 2011-09-20
> 16:03:27.000000000 +0200
> +++ 2011-09-20/xen/drivers/passthrough/amd/pci_amd_iommu.c 2011-09-20
> 16:04:06.000000000 +0200
> @@ -305,7 +305,7 @@ static void amd_iommu_disable_domain_dev
>  }
>  
>  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 @@ static int reassign_device( struct domai
>      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 @@ static int reassign_device( struct domai
>      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 @@ static int amd_iommu_assign_device(struc
>              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 void amd_iommu_domain_destroy(str
>  }
>  
>  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 @@ static int amd_iommu_remove_device(struc
>      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;
> --- 2011-09-20.orig/xen/drivers/passthrough/iommu.c 2011-08-25
> 15:06:35.000000000 +0200
> +++ 2011-09-20/xen/drivers/passthrough/iommu.c 2011-09-15 17:00:38.000000000
> +0200
> @@ -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 @@ int iommu_remove_device(struct pci_dev *
>      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 @@ int assign_device(struct domain *d, u8 b
>          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 @@ int iommu_unmap_page(struct domain *d, u
>  }
>  
>  /* 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 @@ int deassign_device(struct domain *d, u8
>          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 @@ int deassign_device(struct domain *d, u8
>          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 @@ int __init iommu_setup(void)
>      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 @@ int iommu_get_device_group(struct domain
>      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 @@ void iommu_crash_shutdown(void)
>      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
> --- 2011-09-20.orig/xen/drivers/passthrough/pci.c 2011-08-25
> 15:06:35.000000000 +0200
> +++ 2011-09-20/xen/drivers/passthrough/pci.c 2011-08-25 15:06:40.000000000
> +0200
> @@ -441,11 +441,12 @@ void pci_release_devices(struct domain *
>      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);
>  }
> --- 2011-09-20.orig/xen/drivers/passthrough/vtd/iommu.c 2011-09-20
> 16:03:17.000000000 +0200
> +++ 2011-09-20/xen/drivers/passthrough/vtd/iommu.c 2011-09-20
> 16:04:11.000000000 +0200
> @@ -1626,13 +1626,13 @@ out:
>  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;
> @@ -2166,27 +2166,8 @@ int __init intel_vtd_setup(void)
>      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;
> @@ -2197,7 +2178,7 @@ static int intel_iommu_assign_device(str
>          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;
>  
> @@ -2208,7 +2189,7 @@ static int intel_iommu_assign_device(str
>         return -EBUSY;
>      }
>  
> -    ret = reassign_device_ownership(dom0, d, bus, devfn);
> +    ret = reassign_device_ownership(dom0, d, seg, bus, devfn);
>      if ( ret )
>          goto done;
>  
> @@ -2240,7 +2221,7 @@ done:
>      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 )
> --- 2011-09-20.orig/xen/include/public/domctl.h 2011-09-19 10:58:18.000000000
> +0200
> +++ 2011-09-20/xen/include/public/domctl.h 2011-09-15 15:39:21.000000000 +0200
> @@ -455,15 +455,15 @@ DEFINE_XEN_GUEST_HANDLE(xen_domctl_sendt
>  /* 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 */
> --- 2011-09-20.orig/xen/include/xen/iommu.h 2011-08-25 15:06:23.000000000 
> +0200
> +++ 2011-09-20/xen/include/xen/iommu.h 2011-09-15 16:46:28.000000000 +0200
> @@ -74,11 +74,7 @@ int iommu_remove_device(struct pci_dev *
>  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 @@ struct iommu_ops {
>      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_crash_shutdown(void);
>  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-devel mailing list
> Xen-devel@xxxxxxxxxxxxxxxxxxx
> http://lists.xensource.com/xen-devel



_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel