From patchwork Tue Aug 22 14:50:57 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Durrant X-Patchwork-Id: 9915453 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 40F64603F9 for ; Tue, 22 Aug 2017 14:54:18 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 12247288C4 for ; Tue, 22 Aug 2017 14:54:18 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 00BCC288B9; Tue, 22 Aug 2017 14:54:18 +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 B8AEF28886 for ; Tue, 22 Aug 2017 14:54:15 +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 1dkAWS-0002DL-Ht; Tue, 22 Aug 2017 14:51:16 +0000 Received: from mail6.bemta6.messagelabs.com ([193.109.254.103]) by lists.xenproject.org with esmtp (Exim 4.84_2) (envelope-from ) id 1dkAWQ-0002D7-OS for xen-devel@lists.xenproject.org; Tue, 22 Aug 2017 14:51:14 +0000 Received: from [193.109.254.147] by server-3.bemta-6.messagelabs.com id B7/5A-03044-1E44C995; Tue, 22 Aug 2017 14:51:13 +0000 X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFmpikeJIrShJLcpLzFFi42JxWrrBXvehy5x Ig2d7BSy+b5nM5MDocfjDFZYAxijWzLyk/IoE1ozmw6tYCu5bVqw9sI+5gfGJVhcjJ4eEgL/E 9LZXrCA2m4COxNSnl4BsDg4RARWJ23sNuhi5OJgFljJKXPx3gwUkLiwQI7FvLgtIOYuAqsSbz m6wVl4Ba4np99sZIUbKS+xquwgW5xSwkXh4aAJYqxBQza3rgSBhIaDp66fOYoNoFZQ4OfMJ2E hmAQmJgy9eME9g5J2FJDULSWoBI9MqRvXi1KKy1CJdQ72kosz0jJLcxMwcXUMDM73c1OLixPT UnMSkYr3k/NxNjMCwYQCCHYw7nzsdYpTkYFIS5Z38fXakEF9SfkplRmJxRnxRaU5q8SFGGQ4O JQne+c5zIoUEi1LTUyvSMnOAAQyTluDgURLhFQUGsRBvcUFibnFmOkTqFKOilDjvG5A+AZBER mkeXBssai4xykoJ8zICHSLEU5BalJtZgir/ilGcg1FJmPcdyBSezLwSuOmvgBYzAS02bJ0Gsr gkESEl1cDIdtb7Tk41z9Ipqnytgec+moafl5njlFa4T0JtK1+EeniieeTkiJ0frvMvu75a9pO n4P83wfeETxiHcjhfOzRLo6rq8qIZdlMTvn1Jfnn/lQITz6VlClIVXbcjyp72RzFe0vB9pbte 21zqiKPw1CtvS/02lfbvbP/6IsXH/O//7KUphnw2+bpKLMUZiYZazEXFiQBAb/4slQIAAA== X-Env-Sender: prvs=40066d99f=Paul.Durrant@citrix.com X-Msg-Ref: server-3.tower-27.messagelabs.com!1503413471!112630478!1 X-Originating-IP: [66.165.176.63] X-SpamReason: No, hits=0.0 required=7.0 tests=sa_preprocessor: VHJ1c3RlZCBJUDogNjYuMTY1LjE3Ni42MyA9PiAzMDYwNDg=\n, received_headers: No Received headers X-StarScan-Received: X-StarScan-Version: 9.4.45; banners=-,-,- X-VirusChecked: Checked Received: (qmail 11066 invoked from network); 22 Aug 2017 14:51:12 -0000 Received: from smtp02.citrix.com (HELO SMTP02.CITRIX.COM) (66.165.176.63) by server-3.tower-27.messagelabs.com with RC4-SHA encrypted SMTP; 22 Aug 2017 14:51:12 -0000 X-IronPort-AV: E=Sophos;i="5.41,412,1498521600"; d="scan'208";a="444688152" From: Paul Durrant To: Date: Tue, 22 Aug 2017 15:50:57 +0100 Message-ID: <20170822145107.6877-4-paul.durrant@citrix.com> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20170822145107.6877-1-paul.durrant@citrix.com> References: <20170822145107.6877-1-paul.durrant@citrix.com> MIME-Version: 1.0 Cc: George Dunlap , Andrew Cooper , Paul Durrant , Jan Beulich Subject: [Xen-devel] [PATCH v2 REPOST 03/12] x86/mm: add HYPERVISOR_memory_op to acquire guest resources 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 Certain memory resources associated with a guest are not necessarily present in the guest P2M and so are not necessarily available to be foreign-mapped by a tools domain unless they are inserted, which risks shattering a super-page mapping. This patch adds a new memory op to allow such resourced to be priv-mapped directly, by either a PV or HVM tools domain. NOTE: Whilst the new op is not intrinsicly specific to the x86 architecture, I have no means to test it on an ARM platform and so cannot verify that it functions correctly. Hence it is currently only implemented for x86. Signed-off-by: Paul Durrant Acked-by: George Dunlap --- Cc: Jan Beulich Cc: Andrew Cooper Cc: George Dunlap --- xen/arch/x86/mm.c | 111 ++++++++++++++++++++++++++++++++++++++++++++ xen/arch/x86/mm/p2m.c | 3 +- xen/include/asm-x86/p2m.h | 3 ++ xen/include/public/memory.h | 38 ++++++++++++++- 4 files changed, 152 insertions(+), 3 deletions(-) diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c index aaa9ff5197..4e86f0a2ab 100644 --- a/xen/arch/x86/mm.c +++ b/xen/arch/x86/mm.c @@ -4717,6 +4717,107 @@ int xenmem_add_to_physmap_one( return rc; } +static int xenmem_acquire_grant_table(struct domain *d, + unsigned long frame, + unsigned long nr_frames, + unsigned long mfn_list[]) +{ + unsigned int i; + + /* + * Iterate through the list backwards so that gnttab_get_frame() is + * first called for the highest numbered frame. This means that the + * out-of-bounds check will be done on the first iteration and, if + * the table needs to grow, it will only grow once. + */ + i = nr_frames; + while ( i-- != 0 ) + { + mfn_t mfn = gnttab_get_frame(d, frame + i); + + if ( mfn_eq(mfn, INVALID_MFN) ) + return -EINVAL; + + mfn_list[i] = mfn_x(mfn); + } + + return 0; +} + +static int xenmem_acquire_resource(xen_mem_acquire_resource_t *xmar) +{ + struct domain *d, *currd = current->domain; + unsigned long *mfn_list; + int rc; + + if ( xmar->nr_frames == 0 ) + return -EINVAL; + + d = rcu_lock_domain_by_any_id(xmar->domid); + if ( d == NULL ) + return -ESRCH; + + rc = xsm_domain_memory_map(XSM_TARGET, d); + if ( rc ) + goto out; + + mfn_list = xmalloc_array(unsigned long, xmar->nr_frames); + + rc = -ENOMEM; + if ( !mfn_list ) + goto out; + + switch ( xmar->type ) + { + case XENMEM_resource_grant_table: + rc = -EINVAL; + if ( xmar->id ) /* must be zero for grant_table */ + break; + + rc = xenmem_acquire_grant_table(d, xmar->frame, xmar->nr_frames, + mfn_list); + break; + + default: + rc = -EOPNOTSUPP; + break; + } + + if ( rc ) + goto free_and_out; + + if ( !paging_mode_translate(currd) ) + { + if ( __copy_to_guest_offset(xmar->gmfn_list, 0, mfn_list, + xmar->nr_frames) ) + rc = -EFAULT; + } + else + { + unsigned int i; + + for ( i = 0; i < xmar->nr_frames; i++ ) + { + xen_pfn_t gfn; + + rc = -EFAULT; + if ( __copy_from_guest_offset(&gfn, xmar->gmfn_list, i, 1) ) + goto free_and_out; + + rc = set_foreign_p2m_entry(currd, gfn, _mfn(mfn_list[i])); + if ( rc ) + goto free_and_out; + } + } + + free_and_out: + xfree(mfn_list); + + out: + rcu_unlock_domain(d); + return rc; +} + long arch_memory_op(unsigned long cmd, XEN_GUEST_HANDLE_PARAM(void) arg) { int rc; @@ -4939,6 +5040,16 @@ long arch_memory_op(unsigned long cmd, XEN_GUEST_HANDLE_PARAM(void) arg) return rc; } + case XENMEM_acquire_resource: + { + xen_mem_acquire_resource_t xmar; + + if ( copy_from_guest(&xmar, arg, 1) ) + return -EFAULT; + + return xenmem_acquire_resource(&xmar); + } + default: return subarch_memory_op(cmd, arg); } diff --git a/xen/arch/x86/mm/p2m.c b/xen/arch/x86/mm/p2m.c index e8a57d118c..c503a7f1d2 100644 --- a/xen/arch/x86/mm/p2m.c +++ b/xen/arch/x86/mm/p2m.c @@ -1118,8 +1118,7 @@ static int set_typed_p2m_entry(struct domain *d, unsigned long gfn, mfn_t mfn, } /* Set foreign mfn in the given guest's p2m table. */ -static int set_foreign_p2m_entry(struct domain *d, unsigned long gfn, - mfn_t mfn) +int set_foreign_p2m_entry(struct domain *d, unsigned long gfn, mfn_t mfn) { return set_typed_p2m_entry(d, gfn, mfn, PAGE_ORDER_4K, p2m_map_foreign, p2m_get_hostp2m(d)->default_access); diff --git a/xen/include/asm-x86/p2m.h b/xen/include/asm-x86/p2m.h index 6395e8fd1d..3ccec250d8 100644 --- a/xen/include/asm-x86/p2m.h +++ b/xen/include/asm-x86/p2m.h @@ -613,6 +613,9 @@ void p2m_memory_type_changed(struct domain *d); int p2m_is_logdirty_range(struct p2m_domain *, unsigned long start, unsigned long end); +/* Set foreign entry in the p2m table (for priv-mapping) */ +int set_foreign_p2m_entry(struct domain *d, unsigned long gfn, mfn_t mfn); + /* Set mmio addresses in the p2m table (for pass-through) */ int set_mmio_p2m_entry(struct domain *d, unsigned long gfn, mfn_t mfn, unsigned int order, p2m_access_t access); diff --git a/xen/include/public/memory.h b/xen/include/public/memory.h index 29386df98b..9bf58e7384 100644 --- a/xen/include/public/memory.h +++ b/xen/include/public/memory.h @@ -650,7 +650,43 @@ struct xen_vnuma_topology_info { typedef struct xen_vnuma_topology_info xen_vnuma_topology_info_t; DEFINE_XEN_GUEST_HANDLE(xen_vnuma_topology_info_t); -/* Next available subop number is 28 */ +#if defined(__XEN__) || defined(__XEN_TOOLS__) + +/* + * Get the pages for a particular guest resource, so that they can be + * mapped directly by a tools domain. + */ +#define XENMEM_acquire_resource 28 +struct xen_mem_acquire_resource { + /* IN - the domain whose resource is to be mapped */ + domid_t domid; + /* IN - the type of resource (defined below) */ + uint16_t type; + +#define XENMEM_resource_grant_table 0 + + /* + * IN - a type-specific resource identifier, which must be zero + * unless stated otherwise. + */ + uint32_t id; + /* IN - number of (4K) frames of the resource to be mapped */ + uint32_t nr_frames; + /* IN - the index of the initial frame to be mapped */ + uint64_aligned_t frame; + /* IN/OUT - If the tools domain is PV then, upon return, gmfn_list + * will be populated with the MFNs of the resource. + * If the tools domain is HVM then it is expected that, on + * entry, gmfn_list will be populated with a list of GFNs + * that will be mapped to the MFNs of the resource. + */ + XEN_GUEST_HANDLE(xen_pfn_t) gmfn_list; +}; +typedef struct xen_mem_acquire_resource xen_mem_acquire_resource_t; + +#endif /* defined(__XEN__) || defined(__XEN_TOOLS__) */ + +/* Next available subop number is 29 */ #endif /* __XEN_PUBLIC_MEMORY_H__ */