diff --git a/xen/common/domctl.c b/xen/common/domctl.c index a9816b2e58..200b5b3669 100644 --- a/xen/common/domctl.c +++ b/xen/common/domctl.c @@ -325,6 +325,10 @@ long do_domctl(XEN_GUEST_HANDLE_PARAM(xen_domctl_t) u_domctl) case XEN_DOMCTL_deassign_device: if ( op->domain == DOMID_IO ) { +#ifdef CONFIG_HAS_DEVICE_TREE_DISCOVERY + if ( op->u.assign_device.dev == XEN_DOMCTL_DEV_DT ) + op->u.assign_device.u.dt.dev = NULL; +#endif d = dom_io; break; } @@ -332,6 +336,11 @@ long do_domctl(XEN_GUEST_HANDLE_PARAM(xen_domctl_t) u_domctl) return -ESRCH; fallthrough; case XEN_DOMCTL_test_assign_device: +#ifdef CONFIG_HAS_DEVICE_TREE_DISCOVERY + if ( op->u.assign_device.dev == XEN_DOMCTL_DEV_DT ) + op->u.assign_device.u.dt.dev = NULL; + fallthrough; +#endif case XEN_DOMCTL_vm_event_op: if ( op->domain == DOMID_INVALID ) { diff --git a/xen/drivers/passthrough/device_tree.c b/xen/drivers/passthrough/device_tree.c index f5850a2607..ab1e07ac99 100644 --- a/xen/drivers/passthrough/device_tree.c +++ b/xen/drivers/passthrough/device_tree.c @@ -340,15 +340,15 @@ int iommu_do_dt_domctl(struct xen_domctl *domctl, struct domain *d, if ( (d && d->is_dying) || 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_assign_dtdevice(XSM_HOOK, d, dt_node_full_name(dev)); - if ( ret ) - break; + dev = domctl->u.assign_device.u.dt.dev; + if ( !dev ) + { + ret = dt_find_node_by_gpath(domctl->u.assign_device.u.dt.path, + domctl->u.assign_device.u.dt.size, + &dev); + if ( ret ) + break; + } if ( domctl->cmd == XEN_DOMCTL_test_assign_device ) { @@ -396,15 +396,15 @@ int iommu_do_dt_domctl(struct xen_domctl *domctl, struct domain *d, 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_deassign_dtdevice(XSM_HOOK, d, dt_node_full_name(dev)); - if ( ret ) - break; + dev = domctl->u.assign_device.u.dt.dev; + if ( !dev ) + { + ret = dt_find_node_by_gpath(domctl->u.assign_device.u.dt.path, + domctl->u.assign_device.u.dt.size, + &dev); + if ( ret ) + break; + } if ( d == dom_io ) { diff --git a/xen/drivers/passthrough/pci.c b/xen/drivers/passthrough/pci.c index 7991a0f91b..d37ceb7b6c 100644 --- a/xen/drivers/passthrough/pci.c +++ b/xen/drivers/passthrough/pci.c @@ -1823,10 +1823,6 @@ int iommu_do_pci_domctl( machine_sbdf = domctl->u.assign_device.u.pci.machine_sbdf; - ret = xsm_assign_device(XSM_HOOK, d, machine_sbdf); - if ( ret ) - break; - seg = machine_sbdf >> 16; bus = PCI_BUS(machine_sbdf); devfn = PCI_DEVFN(machine_sbdf); @@ -1868,10 +1864,6 @@ int iommu_do_pci_domctl( machine_sbdf = domctl->u.assign_device.u.pci.machine_sbdf; - ret = xsm_deassign_device(XSM_HOOK, d, machine_sbdf); - if ( ret ) - break; - seg = machine_sbdf >> 16; bus = PCI_BUS(machine_sbdf); devfn = PCI_DEVFN(machine_sbdf); diff --git a/xen/include/public/domctl.h b/xen/include/public/domctl.h index 23124547f3..cdf350a290 100644 --- a/xen/include/public/domctl.h +++ b/xen/include/public/domctl.h @@ -575,7 +575,10 @@ struct xen_domctl_assign_device { } pci; struct { uint32_t size; /* Length of the path */ - XEN_GUEST_HANDLE_64(char) path; /* path to the device tree node */ + XEN_GUEST_HANDLE_64(char) path; /* Path to the device tree node */ +#ifdef __XEN__ + struct dt_device_node *dev; /* Resolved device node of the above */ +#endif } dt; } u; }; diff --git a/xen/include/xsm/dummy.h b/xen/include/xsm/dummy.h index ca010387b1..81d9a7ba3b 100644 --- a/xen/include/xsm/dummy.h +++ b/xen/include/xsm/dummy.h @@ -398,40 +398,8 @@ static XSM_INLINE int cf_check xsm_get_device_group( XSM_ASSERT_ACTION(XSM_PRIV); return xsm_default_action(action, current->domain, NULL); } - -static XSM_INLINE int cf_check xsm_assign_device( - XSM_DEFAULT_ARG struct domain *d, uint32_t machine_bdf) -{ - XSM_ASSERT_ACTION(XSM_HOOK); - return xsm_default_action(action, current->domain, d); -} - -static XSM_INLINE int cf_check xsm_deassign_device( - XSM_DEFAULT_ARG struct domain *d, uint32_t machine_bdf) -{ - XSM_ASSERT_ACTION(XSM_HOOK); - return xsm_default_action(action, current->domain, d); -} - #endif /* HAS_PASSTHROUGH && HAS_PCI */ -#if defined(CONFIG_HAS_PASSTHROUGH) && defined(CONFIG_HAS_DEVICE_TREE_DISCOVERY) -static XSM_INLINE int cf_check xsm_assign_dtdevice( - XSM_DEFAULT_ARG struct domain *d, const char *dtpath) -{ - XSM_ASSERT_ACTION(XSM_HOOK); - return xsm_default_action(action, current->domain, d); -} - -static XSM_INLINE int cf_check xsm_deassign_dtdevice( - XSM_DEFAULT_ARG struct domain *d, const char *dtpath) -{ - XSM_ASSERT_ACTION(XSM_HOOK); - return xsm_default_action(action, current->domain, d); -} - -#endif /* HAS_PASSTHROUGH && HAS_DEVICE_TREE_DISCOVERY */ - static XSM_INLINE int cf_check xsm_resource_plug_core(XSM_DEFAULT_VOID) { XSM_ASSERT_ACTION(XSM_HOOK); diff --git a/xen/include/xsm/xsm.h b/xen/include/xsm/xsm.h index dfff432ff1..fb622c62ce 100644 --- a/xen/include/xsm/xsm.h +++ b/xen/include/xsm/xsm.h @@ -122,13 +122,6 @@ struct xsm_ops { #if defined(CONFIG_HAS_PASSTHROUGH) && defined(CONFIG_HAS_PCI) int (*get_device_group)(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_DISCOVERY) - int (*assign_dtdevice)(struct domain *d, const char *dtpath); - int (*deassign_dtdevice)(struct domain *d, const char *dtpath); #endif int (*resource_plug_core)(void); @@ -526,35 +519,8 @@ static inline int xsm_get_device_group(xsm_default_t def, uint32_t machine_bdf) { return alternative_call(xsm_ops.get_device_group, machine_bdf); } - -static inline int xsm_assign_device( - xsm_default_t def, struct domain *d, uint32_t machine_bdf) -{ - return alternative_call(xsm_ops.assign_device, d, machine_bdf); -} - -static inline int xsm_deassign_device( - xsm_default_t def, struct domain *d, uint32_t machine_bdf) -{ - return alternative_call(xsm_ops.deassign_device, d, machine_bdf); -} #endif /* HAS_PASSTHROUGH && HAS_PCI) */ -#if defined(CONFIG_HAS_PASSTHROUGH) && defined(CONFIG_HAS_DEVICE_TREE_DISCOVERY) -static inline int xsm_assign_dtdevice( - xsm_default_t def, struct domain *d, const char *dtpath) -{ - return alternative_call(xsm_ops.assign_dtdevice, d, dtpath); -} - -static inline int xsm_deassign_dtdevice( - xsm_default_t def, struct domain *d, const char *dtpath) -{ - return alternative_call(xsm_ops.deassign_dtdevice, d, dtpath); -} - -#endif /* HAS_PASSTHROUGH && HAS_DEVICE_TREE_DISCOVERY */ - static inline int xsm_resource_plug_pci(xsm_default_t def, uint32_t machine_bdf) { return alternative_call(xsm_ops.resource_plug_pci, machine_bdf); diff --git a/xen/xsm/dummy.c b/xen/xsm/dummy.c index cfa83380e6..6c17bbff3a 100644 --- a/xen/xsm/dummy.c +++ b/xen/xsm/dummy.c @@ -79,13 +79,6 @@ static const struct xsm_ops __initconst_cf_clobber dummy_ops = { #if defined(CONFIG_HAS_PASSTHROUGH) && defined(CONFIG_HAS_PCI) .get_device_group = xsm_get_device_group, - .assign_device = xsm_assign_device, - .deassign_device = xsm_deassign_device, -#endif - -#if defined(CONFIG_HAS_PASSTHROUGH) && defined(CONFIG_HAS_DEVICE_TREE_DISCOVERY) - .assign_dtdevice = xsm_assign_dtdevice, - .deassign_dtdevice = xsm_deassign_dtdevice, #endif .resource_plug_core = xsm_resource_plug_core, diff --git a/xen/xsm/flask/hooks.c b/xen/xsm/flask/hooks.c index 14347ae2fd..fe75412f5e 100644 --- a/xen/xsm/flask/hooks.c +++ b/xen/xsm/flask/hooks.c @@ -44,6 +44,17 @@ static int flask_shadow_control(struct domain *d, unsigned int op); #define pv_shim false #endif +#ifdef CONFIG_HAS_PASSTHROUGH +#ifdef CONFIG_HAS_PCI +static int flask_assign_device(struct domain *d, unsigned int machine_bdf); +static int flask_deassign_device(struct domain *d, unsigned int machine_bdf); +#endif +#ifdef CONFIG_HAS_DEVICE_TREE_DISCOVERY +static int flask_assign_dtdevice(struct domain *d, const char *dtpath); +static int flask_deassign_dtdevice(struct domain *d, const char *dtpath); +#endif +#endif /* CONFIG_HAS_PASSTHROUGH */ + static uint32_t domain_sid(const struct domain *dom) { struct domain_security_struct *dsec = dom->ssid; @@ -667,16 +678,6 @@ static int cf_check flask_domctl(struct domain *d, struct xen_domctl *op) /* These have individual XSM hooks (common/domctl.c) */ case XEN_DOMCTL_set_target: - -#ifdef CONFIG_HAS_PASSTHROUGH - /* - * These have individual XSM hooks - * (drivers/passthrough/{pci,device_tree.c) - */ - case XEN_DOMCTL_test_assign_device: - case XEN_DOMCTL_assign_device: - case XEN_DOMCTL_deassign_device: -#endif return 0; case XEN_DOMCTL_destroydomain: @@ -756,6 +757,49 @@ static int cf_check flask_domctl(struct domain *d, struct xen_domctl *op) return flask_shadow_control(d, op->u.shadow_op.op); #endif +#ifdef CONFIG_HAS_PASSTHROUGH + + case XEN_DOMCTL_test_assign_device: + case XEN_DOMCTL_assign_device: + case XEN_DOMCTL_deassign_device: + switch ( op->u.assign_device.dev ) + { +#ifdef CONFIG_HAS_PCI + case XEN_DOMCTL_DEV_PCI: + return op->cmd != XEN_DOMCTL_deassign_device + ? flask_assign_device( + d, op->u.assign_device.u.pci.machine_sbdf) + : flask_deassign_device( + d, op->u.assign_device.u.pci.machine_sbdf); +#endif + +#ifdef CONFIG_HAS_DEVICE_TREE_DISCOVERY + case XEN_DOMCTL_DEV_DT: + { + struct dt_device_node *dev; + int ret = dt_find_node_by_gpath(op->u.assign_device.u.dt.path, + op->u.assign_device.u.dt.size, + &dev); + + if ( ret ) + return ret; + + op->u.assign_device.u.dt.dev = dev; + + return op->cmd != XEN_DOMCTL_deassign_device + ? flask_assign_dtdevice(d, dt_node_full_name(dev)) + : flask_deassign_dtdevice(d, dt_node_full_name(dev)); + } +#endif + + default: + /* Unknown type. */ + break; + } + return avc_unknown_permission("assign_device", op->cmd); + +#endif /* CONFIG_HAS_PASSTHROUGH */ + case XEN_DOMCTL_mem_sharing_op: return current_has_perm(d, SECCLASS_HVM, HVM__MEM_SHARING); @@ -1379,7 +1423,7 @@ static int flask_test_assign_device(uint32_t machine_bdf) return avc_current_has_perm(rsid, SECCLASS_RESOURCE, RESOURCE__STAT_DEVICE, NULL); } -static int cf_check flask_assign_device(struct domain *d, uint32_t machine_bdf) +static int flask_assign_device(struct domain *d, uint32_t machine_bdf) { uint32_t dsid, rsid; int rc = -EPERM; @@ -1409,7 +1453,7 @@ static int cf_check flask_assign_device(struct domain *d, uint32_t machine_bdf) return avc_has_perm(dsid, rsid, SECCLASS_RESOURCE, dperm, &ad); } -static int cf_check flask_deassign_device( +static int flask_deassign_device( struct domain *d, uint32_t machine_bdf) { uint32_t rsid; @@ -1441,7 +1485,7 @@ static int flask_test_assign_dtdevice(const char *dtpath) NULL); } -static int cf_check flask_assign_dtdevice(struct domain *d, const char *dtpath) +static int flask_assign_dtdevice(struct domain *d, const char *dtpath) { uint32_t dsid, rsid; int rc = -EPERM; @@ -1471,7 +1515,7 @@ static int cf_check flask_assign_dtdevice(struct domain *d, const char *dtpath) return avc_has_perm(dsid, rsid, SECCLASS_RESOURCE, dperm, &ad); } -static int cf_check flask_deassign_dtdevice( +static int flask_deassign_dtdevice( struct domain *d, const char *dtpath) { uint32_t rsid; @@ -1950,13 +1994,6 @@ static const struct xsm_ops __initconst_cf_clobber flask_ops = { #if defined(CONFIG_HAS_PASSTHROUGH) && defined(CONFIG_HAS_PCI) .get_device_group = flask_get_device_group, - .assign_device = flask_assign_device, - .deassign_device = flask_deassign_device, -#endif - -#if defined(CONFIG_HAS_PASSTHROUGH) && defined(CONFIG_HAS_DEVICE_TREE_DISCOVERY) - .assign_dtdevice = flask_assign_dtdevice, - .deassign_dtdevice = flask_deassign_dtdevice, #endif .platform_op = flask_platform_op,