From patchwork Wed Aug 16 12:20:01 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jan Beulich X-Patchwork-Id: 9903579 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id CC953600CA for ; Wed, 16 Aug 2017 12:22:31 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id B8C42289D4 for ; Wed, 16 Aug 2017 12:22:31 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id AD9A1289E5; Wed, 16 Aug 2017 12:22:31 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-4.2 required=2.0 tests=BAYES_00, RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id A7475289DF for ; Wed, 16 Aug 2017 12:22:30 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.84_2) (envelope-from ) id 1dhxIu-0004tB-IE; Wed, 16 Aug 2017 12:20:08 +0000 Received: from mail6.bemta3.messagelabs.com ([195.245.230.39]) by lists.xenproject.org with esmtp (Exim 4.84_2) (envelope-from ) id 1dhxIs-0004t5-IO for xen-devel@lists.xenproject.org; Wed, 16 Aug 2017 12:20:06 +0000 Received: from [85.158.137.68] by server-16.bemta-3.messagelabs.com id C3/8C-01732-57834995; Wed, 16 Aug 2017 12:20:05 +0000 X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFtrAIsWRWlGSWpSXmKPExsXS6fjDS7fEYkq kwY1PZhbft0xmcmD0OPzhCksAYxRrZl5SfkUCa8bLvx8YC5aHVaz44NvAeNihi5GTQ0ggT+L/ //csIDavgJ1EU/cnVhBbQsBQ4vTCm2BxFgFViSMXLoPZbALqEm3PtgPVcHCICBhInDua1MXIx cEs8J9JonfxFDaQGmGBCIlzzzczQ8y3k3jUM5MJpJ5XQFDi7w5hkDCzgJbEw1+3WCBsbYllC1 8zg5QwC0hLLP/HMYGRdxZCwywkDbOQNMxCaFjAyLKKUaM4tagstUjX0EIvqSgzPaMkNzEzR9f QwFgvN7W4ODE9NScxqVgvOT93EyMwxOoZGBh3MP4+7XmIUZKDSUmUN0hrSqQQX1J+SmVGYnFG fFFpTmrxIUYNDg6BZ2tXX2CUYsnLz0tVkuB9YgZUJ1iUmp5akZaZA4wCmFIJDh4lEd6LIGne4 oLE3OLMdIjUKUZdjlcT/n9jEgKbISXOux6kSACkKKM0D24ELCIvMcpKCfMyMjAwCPEUpBblZp agyr9iFOdgVBLmlTAHmsKTmVcCt+kV0BFMQEdcaZ8EckRJIkJKqoFxXtiKGNVV9yc557RL8N+ p7pddXmURWSf6fVmhwqRk1aY/qsGK1yZOTu56XGozJ9X07z0VVenJVy/ue/PglWDu94Z7Fdf+ V03f6pE+d5f4/n0r7GbPtxE3856bpljKY3FSIULZ8d86+TmrTO0vmSWLpfjOd3t11HFJ1KcX2 XX6AWLP5rxeGDtRiaU4I9FQi7moOBEAMilSwMMCAAA= X-Env-Sender: JBeulich@suse.com X-Msg-Ref: server-13.tower-31.messagelabs.com!1502886002!105686198!1 X-Originating-IP: [137.65.248.74] X-SpamReason: No, hits=0.0 required=7.0 tests= X-StarScan-Received: X-StarScan-Version: 9.4.45; banners=-,-,- X-VirusChecked: Checked Received: (qmail 17518 invoked from network); 16 Aug 2017 12:20:04 -0000 Received: from prv-mh.provo.novell.com (HELO prv-mh.provo.novell.com) (137.65.248.74) by server-13.tower-31.messagelabs.com with DHE-RSA-AES256-GCM-SHA384 encrypted SMTP; 16 Aug 2017 12:20:04 -0000 Received: from INET-PRV-MTA by prv-mh.provo.novell.com with Novell_GroupWise; Wed, 16 Aug 2017 06:20:02 -0600 Message-Id: <599454910200007800170490@prv-mh.provo.novell.com> X-Mailer: Novell GroupWise Internet Agent 14.2.2 Date: Wed, 16 Aug 2017 06:20:01 -0600 From: "Jan Beulich" To: "xen-devel" References: <599454910200007800170490@prv-mh.provo.novell.com> Mime-Version: 1.0 Content-Disposition: inline Cc: Stefano Stabellini , Wei Liu , George Dunlap , Andrew Cooper , Ian Jackson , Tim Deegan , Julien Grall , Daniel de Graaf Subject: [Xen-devel] [PATCH v3] passthrough: give XEN_DOMCTL_test_assign_device more sane semantics X-BeenThere: xen-devel@lists.xen.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xen.org Sender: "Xen-devel" X-Virus-Scanned: ClamAV using ClamSMTP 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 Acked-by: Daniel De Graaf Reviewed-by: Wei Liu --- 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