Jan Beulich
2011-Sep-20 15:18 UTC
[Xen-devel] [PATCH 3/7] PCI multi-seg: adjust domctl interface
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)? Signed-off-by: Jan Beulich <jbeulich@suse.com> --- 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@lists.xensource.com http://lists.xensource.com/xen-devel
Keir Fraser
2011-Sep-21 12:37 UTC
Re: [Xen-devel] [PATCH 3/7] PCI multi-seg: adjust domctl interface
On 20/09/2011 08:18, "Jan Beulich" <JBeulich@suse.com> 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@suse.com> > > --- 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@lists.xensource.com > http://lists.xensource.com/xen-devel_______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Stefano Stabellini
2011-Sep-21 12:42 UTC
Re: [Xen-devel] [PATCH 3/7] PCI multi-seg: adjust domctl interface
On Wed, 21 Sep 2011, Keir Fraser wrote:> On 20/09/2011 08:18, "Jan Beulich" <JBeulich@suse.com> 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? >Before b4bb8b3f09d1c873f522f6aebe1f125a6d1854d0 xc_assign_device and xc_deassign_device were called by qemu. Now they are called by libxl. _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Jan Beulich
2011-Sep-21 13:10 UTC
Re: [Xen-devel] [PATCH 3/7] PCI multi-seg: adjust domctl interface
>>> On 21.09.11 at 14:42, Stefano Stabellini <stefano.stabellini@eu.citrix.com>wrote:> On Wed, 21 Sep 2011, Keir Fraser wrote: >> On 20/09/2011 08:18, "Jan Beulich" <JBeulich@suse.com> 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? >> > > Before b4bb8b3f09d1c873f522f6aebe1f125a6d1854d0 xc_assign_device and > xc_deassign_device were called by qemu. Now they are called by libxl.Ian, Keir - what does that mean for my changes then? Do I need to re-spin them? Do I need to even introduce new domctl structures? Or just up the interface version (given that retaining compatibility with old qemu will be impossible anyway the first time the interface version gets changed, unless "old qemu" simply means git://xenbits.xensource.com/qemu-xen-unstable.git rather than my understanding of old, already built binaries)? Jan _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Keir Fraser
2011-Sep-21 13:41 UTC
Re: [Xen-devel] [PATCH 3/7] PCI multi-seg: adjust domctl interface
On 21/09/2011 06:10, "Jan Beulich" <JBeulich@suse.com> wrote:>>>> On 21.09.11 at 14:42, Stefano Stabellini <stefano.stabellini@eu.citrix.com> > wrote: >> On Wed, 21 Sep 2011, Keir Fraser wrote: >>> On 20/09/2011 08:18, "Jan Beulich" <JBeulich@suse.com> 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? >>> >> >> Before b4bb8b3f09d1c873f522f6aebe1f125a6d1854d0 xc_assign_device and >> xc_deassign_device were called by qemu. Now they are called by libxl. > > Ian, Keir - what does that mean for my changes then? Do I need to > re-spin them? Do I need to even introduce new domctl structures? Or > just up the interface version (given that retaining compatibility with > old qemu will be impossible anyway the first time the interface version > gets changed, unless "old qemu" simply means > git://xenbits.xensource.com/qemu-xen-unstable.git rather than my > understanding of old, already built binaries)?I don''t know that old qemu compat matters until we are wanting to support builds of upstream qemu. I''m not sure we are even quite there yet. So far, all our ''old qemus'' are tied to a specific hypervisor version. So I''m not sure we have a problem, and probably your patch is fine. -- Keir> Jan >_______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel