From patchwork Tue Sep 5 11:37:15 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Paul Durrant X-Patchwork-Id: 9938509 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 1A1F3600CB for ; Tue, 5 Sep 2017 11:49:37 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 0B90D2887D for ; Tue, 5 Sep 2017 11:49:37 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 004AD288E8; Tue, 5 Sep 2017 11:49:36 +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 46E792887D for ; Tue, 5 Sep 2017 11:49:36 +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 1dpCJo-0000qc-D8; Tue, 05 Sep 2017 11:47:00 +0000 Received: from mail6.bemta6.messagelabs.com ([193.109.254.103]) by lists.xenproject.org with esmtp (Exim 4.84_2) (envelope-from ) id 1dpCJm-0000qQ-Sy for xen-devel@lists.xenproject.org; Tue, 05 Sep 2017 11:46:58 +0000 Received: from [85.158.143.35] by server-7.bemta-6.messagelabs.com id 1E/40-03610-1BE8EA95; Tue, 05 Sep 2017 11:46:57 +0000 X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFlrKIsWRWlGSWpSXmKPExsXitHSDve6GvnW RBo+nWVt83zKZyYHR4/CHKywBjFGsmXlJ+RUJrBn7b69iKVgYXvF0+iT2BsZOpy5GDg4JAX+J /ReZuhg5OdgEdCSmPr3EChIWEVCRuL3XACTMLPCMSeLPEVYQW1ggRqL74it2kBIWoJLN65VAw rwCNhLzjm5iA7ElBOQldrVdBCvnBIo/v3uIHcQWErCW+HPoLRNEvaDEyZlPWCDGa0q0bv/NDm HLSzRvnc0MUa8isX7qLLYJjHyzkLTMQtIyC0nLAkbmVYzqxalFZalFuuZ6SUWZ6RkluYmZObq GBmZ6uanFxYnpqTmJScV6yfm5mxiBQcYABDsYZ172P8QoycGkJMobmrguUogvKT+lMiOxOCO+ qDQntfgQowwHh5IE768eoJxgUWp6akVaZg4w3GHSEhw8SiK8a7uB0rzFBYm5xZnpEKlTjLocn yZu+MIkxJKXn5cqJc4r2gtUJABSlFGaBzcCFnuXGGWlhHkZgY4S4ilILcrNLEGVf8UozsGoJM xbCjKFJzOvBG7TK6AjmICOqHq5BuSIkkSElFQDo/6lQE5pw8YzvA5vNwimmnROkjHSVoh/JPO O37429tXuaduPT3xcW7vk5HLTB9pndkRHRAlVrTn3aGphLU9S/czzlunt4ne+vd0c6SDqxt66 brYV++udCRZK27L+pXw5ssWmiHvr9ALtVdITWJMsZUREdh3+8HXV/LLV6ht7Zr7M1/R03M/Qo 8RSnJFoqMVcVJwIAJuP50K4AgAA X-Env-Sender: prvs=414c423db=Paul.Durrant@citrix.com X-Msg-Ref: server-15.tower-21.messagelabs.com!1504612015!81122320!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 28474 invoked from network); 5 Sep 2017 11:46:56 -0000 Received: from smtp02.citrix.com (HELO SMTP02.CITRIX.COM) (66.165.176.63) by server-15.tower-21.messagelabs.com with RC4-SHA encrypted SMTP; 5 Sep 2017 11:46:56 -0000 X-IronPort-AV: E=Sophos;i="5.41,480,1498521600"; d="scan'208";a="446547988" From: Paul Durrant To: Date: Tue, 5 Sep 2017 12:37:15 +0100 Message-ID: <20170905113716.3960-12-paul.durrant@citrix.com> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20170905113716.3960-1-paul.durrant@citrix.com> References: <20170905113716.3960-1-paul.durrant@citrix.com> MIME-Version: 1.0 Cc: Stefano Stabellini , Wei Liu , George Dunlap , Andrew Cooper , Ian Jackson , Tim Deegan , Paul Durrant , Jan Beulich Subject: [Xen-devel] [PATCH v4 11/12] x86/hvm/ioreq: defer mapping gfns until they are actually requsted 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 A subsequent patch will introduce a new scheme to allow an emulator to map ioreq server pages directly from Xen rather than the guest P2M. This patch lays the groundwork for that change by deferring mapping of gfns until their values are requested by an emulator. To that end, the pad field of the xen_dm_op_get_ioreq_server_info structure is re-purposed to a flags field and new flag, XEN_DMOP_no_gfns, defined which modifies the behaviour of XEN_DMOP_get_ioreq_server_info to allow the caller to avoid requesting the gfn values. Signed-off-by: Paul Durrant Reviewed-by: Roger Pau Monné --- Cc: Ian Jackson Cc: Wei Liu Cc: Andrew Cooper Cc: George Dunlap Cc: Jan Beulich Cc: Konrad Rzeszutek Wilk Cc: Stefano Stabellini Cc: Tim Deegan v3: - Updated in response to review comments from Wei and Roger. - Added a HANDLE_BUFIOREQ macro to make the code neater. - This patch no longer introduces a security vulnerability since there is now an explicit limit on the number of ioreq servers that may be created for any one domain. --- tools/libs/devicemodel/core.c | 8 +++++ tools/libs/devicemodel/include/xendevicemodel.h | 6 ++-- xen/arch/x86/hvm/dm.c | 9 ++++-- xen/arch/x86/hvm/ioreq.c | 41 +++++++++++++------------ xen/include/asm-x86/hvm/domain.h | 2 +- xen/include/public/hvm/dm_op.h | 32 +++++++++++-------- 6 files changed, 59 insertions(+), 39 deletions(-) diff --git a/tools/libs/devicemodel/core.c b/tools/libs/devicemodel/core.c index fcb260d29b..28958934bf 100644 --- a/tools/libs/devicemodel/core.c +++ b/tools/libs/devicemodel/core.c @@ -188,6 +188,14 @@ int xendevicemodel_get_ioreq_server_info( data->id = id; + /* + * If the caller is not requesting gfn values then instruct the + * hypercall not to retrieve them as this may cause them to be + * mapped. + */ + if (!ioreq_gfn && !bufioreq_gfn) + data->flags |= XEN_DMOP_no_gfns; + rc = xendevicemodel_op(dmod, domid, 1, &op, sizeof(op)); if (rc) return rc; diff --git a/tools/libs/devicemodel/include/xendevicemodel.h b/tools/libs/devicemodel/include/xendevicemodel.h index 13216db04a..d73a76da35 100644 --- a/tools/libs/devicemodel/include/xendevicemodel.h +++ b/tools/libs/devicemodel/include/xendevicemodel.h @@ -61,11 +61,11 @@ int xendevicemodel_create_ioreq_server( * @parm domid the domain id to be serviced * @parm id the IOREQ Server id. * @parm ioreq_gfn pointer to a xen_pfn_t to receive the synchronous ioreq - * gfn + * gfn. (May be NULL if not required) * @parm bufioreq_gfn pointer to a xen_pfn_t to receive the buffered ioreq - * gfn + * gfn. (May be NULL if not required) * @parm bufioreq_port pointer to a evtchn_port_t to receive the buffered - * ioreq event channel + * ioreq event channel. (May be NULL if not required) * @return 0 on success, -1 on failure. */ int xendevicemodel_get_ioreq_server_info( diff --git a/xen/arch/x86/hvm/dm.c b/xen/arch/x86/hvm/dm.c index 87ef4b6ca9..c020f0c99f 100644 --- a/xen/arch/x86/hvm/dm.c +++ b/xen/arch/x86/hvm/dm.c @@ -418,16 +418,19 @@ static int dm_op(const struct dmop_args *op_args) { struct xen_dm_op_get_ioreq_server_info *data = &op.u.get_ioreq_server_info; + const uint16_t valid_flags = XEN_DMOP_no_gfns; const_op = false; rc = -EINVAL; - if ( data->pad ) + if ( data->flags & ~valid_flags ) break; rc = hvm_get_ioreq_server_info(d, data->id, - &data->ioreq_gfn, - &data->bufioreq_gfn, + (data->flags & XEN_DMOP_no_gfns) ? + NULL : &data->ioreq_gfn, + (data->flags & XEN_DMOP_no_gfns) ? + NULL : &data->bufioreq_gfn, &data->bufioreq_port); break; } diff --git a/xen/arch/x86/hvm/ioreq.c b/xen/arch/x86/hvm/ioreq.c index 685f6a4858..158bfbba32 100644 --- a/xen/arch/x86/hvm/ioreq.c +++ b/xen/arch/x86/hvm/ioreq.c @@ -344,6 +344,9 @@ static void hvm_update_ioreq_evtchn(struct hvm_ioreq_server *s, } } +#define HANDLE_BUFIOREQ(s) \ + (s->bufioreq_handling != HVM_IOREQSRV_BUFIOREQ_OFF) + static int hvm_ioreq_server_add_vcpu(struct hvm_ioreq_server *s, struct vcpu *v) { @@ -365,7 +368,7 @@ static int hvm_ioreq_server_add_vcpu(struct hvm_ioreq_server *s, sv->ioreq_evtchn = rc; - if ( v->vcpu_id == 0 && s->bufioreq.va != NULL ) + if ( v->vcpu_id == 0 && HANDLE_BUFIOREQ(s) ) { struct domain *d = s->domain; @@ -416,7 +419,7 @@ static void hvm_ioreq_server_remove_vcpu(struct hvm_ioreq_server *s, list_del(&sv->list_entry); - if ( v->vcpu_id == 0 && s->bufioreq.va != NULL ) + if ( v->vcpu_id == 0 && HANDLE_BUFIOREQ(s) ) free_xen_event_channel(v->domain, s->bufioreq_evtchn); free_xen_event_channel(v->domain, sv->ioreq_evtchn); @@ -443,7 +446,7 @@ static void hvm_ioreq_server_remove_all_vcpus(struct hvm_ioreq_server *s) list_del(&sv->list_entry); - if ( v->vcpu_id == 0 && s->bufioreq.va != NULL ) + if ( v->vcpu_id == 0 && HANDLE_BUFIOREQ(s) ) free_xen_event_channel(v->domain, s->bufioreq_evtchn); free_xen_event_channel(v->domain, sv->ioreq_evtchn); @@ -454,14 +457,13 @@ static void hvm_ioreq_server_remove_all_vcpus(struct hvm_ioreq_server *s) spin_unlock(&s->lock); } -static int hvm_ioreq_server_map_pages(struct hvm_ioreq_server *s, - bool handle_bufioreq) +static int hvm_ioreq_server_map_pages(struct hvm_ioreq_server *s) { int rc; rc = hvm_map_ioreq_gfn(s, false); - if ( !rc && handle_bufioreq ) + if ( !rc && HANDLE_BUFIOREQ(s) ) rc = hvm_map_ioreq_gfn(s, true); if ( rc ) @@ -589,13 +591,7 @@ static int hvm_ioreq_server_init(struct hvm_ioreq_server *s, if ( rc ) return rc; - if ( bufioreq_handling == HVM_IOREQSRV_BUFIOREQ_ATOMIC ) - s->bufioreq_atomic = true; - - rc = hvm_ioreq_server_map_pages( - s, bufioreq_handling != HVM_IOREQSRV_BUFIOREQ_OFF); - if ( rc ) - goto fail_map; + s->bufioreq_handling = bufioreq_handling; for_each_vcpu ( d, v ) { @@ -610,9 +606,6 @@ static int hvm_ioreq_server_init(struct hvm_ioreq_server *s, hvm_ioreq_server_remove_all_vcpus(s); hvm_ioreq_server_unmap_pages(s); - fail_map: - hvm_ioreq_server_free_rangesets(s); - return rc; } @@ -745,11 +738,20 @@ int hvm_get_ioreq_server_info(struct domain *d, ioservid_t id, if ( !s || IS_DEFAULT(s) ) goto out; + if ( ioreq_gfn || bufioreq_gfn ) + { + rc = hvm_ioreq_server_map_pages(s); + if ( rc ) + goto out; + } + *ioreq_gfn = gfn_x(s->ioreq.gfn); - if ( s->bufioreq.va != NULL ) + if ( HANDLE_BUFIOREQ(s) ) { - *bufioreq_gfn = gfn_x(s->bufioreq.gfn); + if ( bufioreq_gfn ) + *bufioreq_gfn = gfn_x(s->bufioreq.gfn); + *bufioreq_port = s->bufioreq_evtchn; } @@ -1249,7 +1251,8 @@ static int hvm_send_buffered_ioreq(struct hvm_ioreq_server *s, ioreq_t *p) pg->ptrs.write_pointer += qw ? 2 : 1; /* Canonicalize read/write pointers to prevent their overflow. */ - while ( s->bufioreq_atomic && qw++ < IOREQ_BUFFER_SLOT_NUM && + while ( (s->bufioreq_handling == HVM_IOREQSRV_BUFIOREQ_ATOMIC) && + qw++ < IOREQ_BUFFER_SLOT_NUM && pg->ptrs.read_pointer >= IOREQ_BUFFER_SLOT_NUM ) { union bufioreq_pointers old = pg->ptrs, new; diff --git a/xen/include/asm-x86/hvm/domain.h b/xen/include/asm-x86/hvm/domain.h index 2be9353e37..4491a96350 100644 --- a/xen/include/asm-x86/hvm/domain.h +++ b/xen/include/asm-x86/hvm/domain.h @@ -68,8 +68,8 @@ struct hvm_ioreq_server { spinlock_t bufioreq_lock; evtchn_port_t bufioreq_evtchn; struct rangeset *range[NR_IO_RANGE_TYPES]; + int bufioreq_handling; bool enabled; - bool bufioreq_atomic; }; /* diff --git a/xen/include/public/hvm/dm_op.h b/xen/include/public/hvm/dm_op.h index 6bbab5fca3..9677bd74e7 100644 --- a/xen/include/public/hvm/dm_op.h +++ b/xen/include/public/hvm/dm_op.h @@ -79,28 +79,34 @@ struct xen_dm_op_create_ioreq_server { * XEN_DMOP_get_ioreq_server_info: Get all the information necessary to * access IOREQ Server . * - * The emulator needs to map the synchronous ioreq structures and buffered - * ioreq ring (if it exists) that Xen uses to request emulation. These are - * hosted in the target domain's gmfns and - * respectively. In addition, if the IOREQ Server is handling buffered - * emulation requests, the emulator needs to bind to event channel - * to listen for them. (The event channels used for - * synchronous emulation requests are specified in the per-CPU ioreq - * structures in ). - * If the IOREQ Server is not handling buffered emulation requests then the - * values handed back in and will both be 0. + * If the IOREQ Server is handling buffered emulation requests, the + * emulator needs to bind to event channel to listen for + * them. (The event channels used for synchronous emulation requests are + * specified in the per-CPU ioreq structures). + * In addition, if the XENMEM_acquire_resource memory op cannot be used, + * the emulator will need to map the synchronous ioreq structures and + * buffered ioreq ring (if it exists) from guest memory. If does + * not contain XEN_DMOP_no_gfns then these pages will be made available and + * the frame numbers passed back in gfns and + * respectively. (If the IOREQ Server is not handling buffered emulation + * only will be valid). */ #define XEN_DMOP_get_ioreq_server_info 2 struct xen_dm_op_get_ioreq_server_info { /* IN - server id */ ioservid_t id; - uint16_t pad; + /* IN - flags */ + uint16_t flags; + +#define _XEN_DMOP_no_gfns 0 +#define XEN_DMOP_no_gfns (1u << _XEN_DMOP_no_gfns) + /* OUT - buffered ioreq port */ evtchn_port_t bufioreq_port; - /* OUT - sync ioreq gfn */ + /* OUT - sync ioreq gfn (see block comment above) */ uint64_aligned_t ioreq_gfn; - /* OUT - buffered ioreq gfn */ + /* OUT - buffered ioreq gfn (see block comment above)*/ uint64_aligned_t bufioreq_gfn; };