[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH 3/7] PCI multi-seg: adjust domctl interface
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
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |