|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH v3] 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.
Drop XSM's test_assign_{,dt}device hooks as no longer being
individually useful.
Signed-off-by: Jan Beulich <jbeulich@xxxxxxxx>
---
v3: Drop test-assign XSM hooks.
v2: Alter the semantics to check whether the device can be assigned to
the passed in domain.
--- 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,
@@ -161,6 +164,17 @@ int iommu_do_dt_domctl(struct xen_domctl
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 +208,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
@@ -1583,35 +1583,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 )
{
@@ -1625,7 +1600,9 @@ 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;
@@ -1638,8 +1615,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:
--- a/xen/include/xsm/dummy.h
+++ b/xen/include/xsm/dummy.h
@@ -337,12 +337,6 @@ static XSM_INLINE int xsm_get_device_gro
return xsm_default_action(action, current->domain, NULL);
}
-static XSM_INLINE int xsm_test_assign_device(XSM_DEFAULT_ARG uint32_t
machine_bdf)
-{
- XSM_ASSERT_ACTION(XSM_HOOK);
- return xsm_default_action(action, current->domain, NULL);
-}
-
static XSM_INLINE int xsm_assign_device(XSM_DEFAULT_ARG struct domain *d,
uint32_t machine_bdf)
{
XSM_ASSERT_ACTION(XSM_HOOK);
@@ -358,12 +352,6 @@ static XSM_INLINE int xsm_deassign_devic
#endif /* HAS_PASSTHROUGH && HAS_PCI */
#if defined(CONFIG_HAS_PASSTHROUGH) && defined(CONFIG_HAS_DEVICE_TREE)
-static XSM_INLINE int xsm_test_assign_dtdevice(XSM_DEFAULT_ARG const char
*dtpath)
-{
- XSM_ASSERT_ACTION(XSM_HOOK);
- return xsm_default_action(action, current->domain, NULL);
-}
-
static XSM_INLINE int xsm_assign_dtdevice(XSM_DEFAULT_ARG struct domain *d,
const char *dtpath)
{
--- a/xen/include/xsm/xsm.h
+++ b/xen/include/xsm/xsm.h
@@ -109,13 +109,11 @@ struct xsm_operations {
#if defined(CONFIG_HAS_PASSTHROUGH) && defined(CONFIG_HAS_PCI)
int (*get_device_group) (uint32_t machine_bdf);
- int (*test_assign_device) (uint32_t machine_bdf);
int (*assign_device) (struct domain *d, uint32_t machine_bdf);
int (*deassign_device) (struct domain *d, uint32_t machine_bdf);
#endif
#if defined(CONFIG_HAS_PASSTHROUGH) && defined(CONFIG_HAS_DEVICE_TREE)
- int (*test_assign_dtdevice) (const char *dtpath);
int (*assign_dtdevice) (struct domain *d, const char *dtpath);
int (*deassign_dtdevice) (struct domain *d, const char *dtpath);
#endif
@@ -465,11 +463,6 @@ static inline int xsm_get_device_group(x
return xsm_ops->get_device_group(machine_bdf);
}
-static inline int xsm_test_assign_device(xsm_default_t def, uint32_t
machine_bdf)
-{
- return xsm_ops->test_assign_device(machine_bdf);
-}
-
static inline int xsm_assign_device(xsm_default_t def, struct domain *d,
uint32_t machine_bdf)
{
return xsm_ops->assign_device(d, machine_bdf);
@@ -488,12 +481,6 @@ static inline int xsm_assign_dtdevice(xs
return xsm_ops->assign_dtdevice(d, dtpath);
}
-static inline int xsm_test_assign_dtdevice(xsm_default_t def,
- const char *dtpath)
-{
- return xsm_ops->test_assign_dtdevice(dtpath);
-}
-
static inline int xsm_deassign_dtdevice(xsm_default_t def, struct domain *d,
const char *dtpath)
{
--- a/xen/xsm/dummy.c
+++ b/xen/xsm/dummy.c
@@ -91,13 +91,11 @@ void __init xsm_fixup_ops (struct xsm_op
#if defined(CONFIG_HAS_PASSTHROUGH) && defined(CONFIG_HAS_PCI)
set_to_dummy_if_null(ops, get_device_group);
- set_to_dummy_if_null(ops, test_assign_device);
set_to_dummy_if_null(ops, assign_device);
set_to_dummy_if_null(ops, deassign_device);
#endif
#if defined(CONFIG_HAS_PASSTHROUGH) && defined(CONFIG_HAS_DEVICE_TREE)
- set_to_dummy_if_null(ops, test_assign_dtdevice);
set_to_dummy_if_null(ops, assign_dtdevice);
set_to_dummy_if_null(ops, deassign_dtdevice);
#endif
--- a/xen/xsm/flask/hooks.c
+++ b/xen/xsm/flask/hooks.c
@@ -1278,6 +1281,9 @@ static int flask_assign_device(struct do
int rc = -EPERM;
struct avc_audit_data ad;
+ if ( !d )
+ return flask_test_assign_device(machine_bdf);
+
rc = current_has_perm(d, SECCLASS_RESOURCE, RESOURCE__ADD);
if ( rc )
return rc;
@@ -1333,6 +1339,9 @@ static int flask_assign_dtdevice(struct
int rc = -EPERM;
struct avc_audit_data ad;
+ if ( !d )
+ return flask_test_assign_dtdevice(dtpath);
+
rc = current_has_perm(d, SECCLASS_RESOURCE, RESOURCE__ADD);
if ( rc )
return rc;
@@ -1780,13 +1789,11 @@ static struct xsm_operations flask_ops =
#if defined(CONFIG_HAS_PASSTHROUGH) && defined(CONFIG_HAS_PCI)
.get_device_group = flask_get_device_group,
- .test_assign_device = flask_test_assign_device,
.assign_device = flask_assign_device,
.deassign_device = flask_deassign_device,
#endif
#if defined(CONFIG_HAS_PASSTHROUGH) && defined(CONFIG_HAS_DEVICE_TREE)
- .test_assign_dtdevice = flask_test_assign_dtdevice,
.assign_dtdevice = flask_assign_dtdevice,
.deassign_dtdevice = flask_deassign_dtdevice,
#endif
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
https://lists.xen.org/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |