[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH v2] passthrough: give XEN_DOMCTL_test_assign_device more sane semantics
So far callers of the libxc interface passed in a domain ID which was then ignored in the hypervisor. Instead, make the hypervisor honor it (accepting DOMID_INVALID to obtain original behavior), allowing to query whether a device can be assigned to a particular domain. Signed-off-by: Jan Beulich <jbeulich@xxxxxxxx> --- v2: Alter the semantics to check whether the device can be assigned to the passed in domain. TBD: It's not clear to me whether the test-assign XSM hooks are still useful this way. --- a/xen/common/domctl.c +++ b/xen/common/domctl.c @@ -391,11 +391,15 @@ long do_domctl(XEN_GUEST_HANDLE_PARAM(xe switch ( op->cmd ) { - case XEN_DOMCTL_createdomain: case XEN_DOMCTL_test_assign_device: + if ( op->domain == DOMID_INVALID ) + { + case XEN_DOMCTL_createdomain: case XEN_DOMCTL_gdbsx_guestmemio: - d = NULL; - break; + d = NULL; + break; + } + /* fall through */ default: d = rcu_lock_domain_by_id(op->domain); if ( !d && op->cmd != XEN_DOMCTL_getdomaininfo ) --- a/xen/drivers/passthrough/device_tree.c +++ b/xen/drivers/passthrough/device_tree.c @@ -143,12 +143,15 @@ int iommu_do_dt_domctl(struct xen_domctl switch ( domctl->cmd ) { case XEN_DOMCTL_assign_device: + ASSERT(d); + /* fall through */ + case XEN_DOMCTL_test_assign_device: ret = -ENODEV; if ( domctl->u.assign_device.dev != XEN_DOMCTL_DEV_DT ) break; ret = -EINVAL; - if ( d->is_dying || domctl->u.assign_device.flags ) + if ( (d && d->is_dying) || domctl->u.assign_device.flags ) break; ret = dt_find_node_by_gpath(domctl->u.assign_device.u.dt.path, @@ -157,10 +160,22 @@ int iommu_do_dt_domctl(struct xen_domctl if ( ret ) break; - ret = xsm_assign_dtdevice(XSM_HOOK, d, dt_node_full_name(dev)); + ret = d ? xsm_assign_dtdevice(XSM_HOOK, d, dt_node_full_name(dev)) + : xsm_test_assign_dtdevice(XSM_HOOK, dt_node_full_name(dev)); if ( ret ) break; + if ( domctl->cmd == XEN_DOMCTL_test_assign_device ) + { + if ( iommu_dt_device_is_assigned(dev) ) + { + printk(XENLOG_G_ERR "%s already assigned.\n", + dt_node_full_name(dev)); + ret = -EINVAL; + } + break; + } + ret = iommu_assign_dt_device(d, dev); if ( ret ) @@ -194,33 +209,6 @@ int iommu_do_dt_domctl(struct xen_domctl dt_node_full_name(dev), d->domain_id, ret); break; - case XEN_DOMCTL_test_assign_device: - ret = -ENODEV; - if ( domctl->u.assign_device.dev != XEN_DOMCTL_DEV_DT ) - break; - - ret = -EINVAL; - if ( domctl->u.assign_device.flags ) - break; - - ret = dt_find_node_by_gpath(domctl->u.assign_device.u.dt.path, - domctl->u.assign_device.u.dt.size, - &dev); - if ( ret ) - break; - - ret = xsm_test_assign_dtdevice(XSM_HOOK, dt_node_full_name(dev)); - if ( ret ) - break; - - if ( iommu_dt_device_is_assigned(dev) ) - { - printk(XENLOG_G_ERR "%s already assigned.\n", - dt_node_full_name(dev)); - ret = -EINVAL; - } - break; - default: ret = -ENOSYS; break; --- a/xen/drivers/passthrough/pci.c +++ b/xen/drivers/passthrough/pci.c @@ -1579,35 +1579,10 @@ int iommu_do_pci_domctl( } break; - case XEN_DOMCTL_test_assign_device: - ret = -ENODEV; - if ( domctl->u.assign_device.dev != XEN_DOMCTL_DEV_PCI ) - break; - - ret = -EINVAL; - if ( domctl->u.assign_device.flags ) - break; - - machine_sbdf = domctl->u.assign_device.u.pci.machine_sbdf; - - ret = xsm_test_assign_device(XSM_HOOK, machine_sbdf); - if ( ret ) - break; - - seg = machine_sbdf >> 16; - bus = PCI_BUS(machine_sbdf); - devfn = PCI_DEVFN2(machine_sbdf); - - if ( device_assigned(seg, bus, devfn) ) - { - printk(XENLOG_G_INFO - "%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: + ASSERT(d); + /* fall through */ + case XEN_DOMCTL_test_assign_device: /* Don't support self-assignment of devices. */ if ( d == current->domain ) { @@ -1621,12 +1596,15 @@ int iommu_do_pci_domctl( ret = -EINVAL; flags = domctl->u.assign_device.flags; - if ( d->is_dying || (flags & ~XEN_DOMCTL_DEV_RDM_RELAXED) ) + if ( domctl->cmd == XEN_DOMCTL_assign_device + ? d->is_dying || (flags & ~XEN_DOMCTL_DEV_RDM_RELAXED) + : flags ) break; machine_sbdf = domctl->u.assign_device.u.pci.machine_sbdf; - ret = xsm_assign_device(XSM_HOOK, d, machine_sbdf); + ret = d ? xsm_assign_device(XSM_HOOK, d, machine_sbdf) + : xsm_test_assign_device(XSM_HOOK, machine_sbdf); if ( ret ) break; @@ -1634,8 +1612,20 @@ int iommu_do_pci_domctl( bus = PCI_BUS(machine_sbdf); devfn = PCI_DEVFN2(machine_sbdf); - ret = device_assigned(seg, bus, devfn) ?: - assign_device(d, seg, bus, devfn, flags); + ret = device_assigned(seg, bus, devfn); + if ( domctl->cmd == XEN_DOMCTL_test_assign_device ) + { + if ( ret ) + { + printk(XENLOG_G_INFO + "%04x:%02x:%02x.%u already assigned, or non-existent\n", + seg, bus, PCI_SLOT(devfn), PCI_FUNC(devfn)); + ret = -EINVAL; + } + break; + } + if ( !ret ) + ret = assign_device(d, seg, bus, devfn, flags); if ( ret == -ERESTART ) ret = hypercall_create_continuation(__HYPERVISOR_domctl, "h", u_domctl); --- a/xen/include/public/domctl.h +++ b/xen/include/public/domctl.h @@ -506,7 +506,11 @@ DEFINE_XEN_GUEST_HANDLE(xen_domctl_sendt /* Assign a device to a guest. Sets up IOMMU structures. */ /* XEN_DOMCTL_assign_device */ -/* XEN_DOMCTL_test_assign_device */ +/* + * XEN_DOMCTL_test_assign_device: Pass DOMID_INVALID to find out whether the + * given device is assigned to any DomU at all. Pass a specific domain ID to + * find out whether the given device can be assigned to that domain. + */ /* * XEN_DOMCTL_deassign_device: The behavior of this DOMCTL differs * between the different type of device: _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx https://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |