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
|