From patchwork Thu Apr 27 07:22:24 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Razvan Cojocaru X-Patchwork-Id: 9702437 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 C077E6032C for ; Thu, 27 Apr 2017 07:25:50 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id AB4E62857D for ; Thu, 27 Apr 2017 07:25:50 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 9DAA528437; Thu, 27 Apr 2017 07:25:50 +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 D788228437 for ; Thu, 27 Apr 2017 07:25:49 +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 1d3dlB-0004AS-8n; Thu, 27 Apr 2017 07:22:41 +0000 Received: from mail6.bemta3.messagelabs.com ([195.245.230.39]) by lists.xenproject.org with esmtp (Exim 4.84_2) (envelope-from ) id 1d3dlA-0004AM-1o for xen-devel@lists.xen.org; Thu, 27 Apr 2017 07:22:40 +0000 Received: from [85.158.137.68] by server-6.bemta-3.messagelabs.com id 20/3D-02189-F3C91095; Thu, 27 Apr 2017 07:22:39 +0000 X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFprLIsWRWlGSWpSXmKPExsUSfTxjoa7dHMZ Ig9vnpS2WfFzM4sDocXT3b6YAxijWzLyk/IoE1oyzxwoL+nQr9iz9z9jAeEuli5GDQ0jAQ2Lt 2sIuRk4gcy2jxIoZLF2MXED2NUaJ02c3sUAkPCT6Z39lhUjsZ5S4/nc9K0iCTcBQYvXGFjYQW 0RAWuLa58uMIDazQKlE5+0GdhBbWCBKou3/B7BBLAKqEnPX3GACsXmBhl4+fwOsV0JATuLksc msEHaORNeWFewgx0kISEn8b1UC2SshsIJF4uTKq8wQNTISjybeZJvAKLCAkWEVo0ZxalFZapG uoaleUlFmekZJbmJmjq6hgbFebmpxcWJ6ak5iUrFecn7uJkZgUDEAwQ7GNds9DzFKcjApifIe 62KMFOJLyk+pzEgszogvKs1JLT7EKMPBoSTBGz8bKCdYlJqeWpGWmQMMb5i0BAePkghEmre4I DG3ODMdInWKUZfj3dIP75mEWPLy81KlxHlVZwEVCYAUZZTmwY2AxdolRlkpYV5GoKOEeApSi3 IzS1DlXzGKczAqCfMeBJnCk5lXArfpFdARTEBHsLgwgBxRkoiQkmpgLBSzFtzIZDNxwaTnujn XfL4KT7lQ5xIg/sDSPK3nwANe20ez+TUb1/zP2nGG/ejXDlnTrJkhadl7Y/oKXF49XqetfuHB S5Z7HBKpAa/lzaY0JFSKy4QfO1aZvvlZ932jG8vefOt9zi3KrHni6/YXSkovJvJ278/OnbTX9 dKxB5fKHZ8dF7NSVGIpzkg01GIuKk4EAIXBsk2wAgAA X-Env-Sender: rcojocaru@bitdefender.com X-Msg-Ref: server-10.tower-31.messagelabs.com!1493277758!96927702!1 X-Originating-IP: [91.199.104.161] X-SpamReason: No, hits=0.0 required=7.0 tests= X-StarScan-Received: X-StarScan-Version: 9.4.12; banners=-,-,- X-VirusChecked: Checked Received: (qmail 23848 invoked from network); 27 Apr 2017 07:22:38 -0000 Received: from mx01.bbu.dsd.mx.bitdefender.com (HELO mx01.bbu.dsd.mx.bitdefender.com) (91.199.104.161) by server-10.tower-31.messagelabs.com with DHE-RSA-AES128-GCM-SHA256 encrypted SMTP; 27 Apr 2017 07:22:38 -0000 Received: (qmail 20126 invoked from network); 27 Apr 2017 10:22:36 +0300 Received: from unknown (HELO mx-sr.buh.bitdefender.com) (10.17.80.103) by mx01.bbu.dsd.mx.bitdefender.com with AES256-GCM-SHA384 encrypted SMTP; 27 Apr 2017 10:22:36 +0300 Received: from smtp01.buh.bitdefender.com (smtp.bitdefender.biz [10.17.80.75]) by mx-sr.buh.bitdefender.com (Postfix) with ESMTP id CB9307FC02 for ; Thu, 27 Apr 2017 10:22:36 +0300 (EEST) Received: (qmail 20895 invoked from network); 27 Apr 2017 10:22:36 +0300 Received: from xen.dsd.ro (HELO xen.dsd.bitdefender.biz) (rcojocaru@bitdefender.com@10.10.14.109) by smtp01.buh.bitdefender.com with AES128-SHA256 encrypted SMTP; 27 Apr 2017 10:22:36 +0300 From: Razvan Cojocaru To: xen-devel@lists.xen.org Date: Thu, 27 Apr 2017 10:22:24 +0300 Message-Id: <1493277744-9032-1-git-send-email-rcojocaru@bitdefender.com> X-Mailer: git-send-email 1.9.1 X-BitDefender-Scanner: Clean, Agent: BitDefender qmail 3.1.6 on smtp01.buh.bitdefender.com, sigver: 7.71089 X-BitDefender-Spam: No (0) X-BitDefender-SpamStamp: Build: [Engines: 2.15.8.1074, Dats: 447410, Stamp: 3], Multi: [Enabled, t: (0.000012, 0.027744)], BW: [Enabled, t: (0.000017)], RBL DNSBL: [Disabled], APM: [Enabled, Score: 500, t: (0.007682), Flags: 85D2ED72; NN_NO_CONTENT_TYPE; NN_LEGIT_SUMM_400_WORDS; NN_NO_LINK_NMD; NN_LEGIT_BITDEFENDER; NN_LEGIT_S_SQARE_BRACKETS; NN_LEGIT_MAILING_LIST_TO], SGN: [Enabled, t: (0.014642,0.000318)], URL: [Enabled, t: (0.000006)], RTDA: [Enabled, t: (0.360397), Hit: No, Details: v2.4.6; Id: 11.5euo8b.1be3juhnk.5jqqd], total: 0(775) X-BitDefender-CF-Stamp: none Cc: andrew.cooper3@citrix.com, tamas@tklengyel.com, Razvan Cojocaru , jbeulich@suse.com Subject: [Xen-devel] [PATCH] x86/vm_event: fix race between vmx_vmexit_handler() and vm_event_resume() 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: , MIME-Version: 1.0 Errors-To: xen-devel-bounces@lists.xen.org Sender: "Xen-devel" X-Virus-Scanned: ClamAV using ClamSMTP The introspection agent can reply to a vm_event faster than vmx_vmexit_handler() can complete in some cases, where it is then not safe for vm_event_set_registers() to modify v->arch.user_regs. This patch ensures that vm_event_resume() code only sets per-VCPU data to be used for the actual setting of registers only in hvm_do_resume() (similar to the model used to control setting of CRs and MSRs). The patch additionally removes the sync_vcpu_execstate(v) call from vm_event_resume(), which is no longer necessary, which removes the associated broadcast TLB flush (read: performance improvement). Signed-off-by: Razvan Cojocaru Signed-off-by: Andrew Cooper --- xen/arch/x86/hvm/hvm.c | 35 +++++++++++++++++++++++++++++++++++ xen/arch/x86/vm_event.c | 22 ++-------------------- xen/common/vm_event.c | 14 +++++++------- xen/include/asm-x86/vm_event.h | 2 ++ 4 files changed, 46 insertions(+), 27 deletions(-) diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c index a441955..520942a 100644 --- a/xen/arch/x86/hvm/hvm.c +++ b/xen/arch/x86/hvm/hvm.c @@ -473,6 +473,39 @@ static bool hvm_get_pending_event(struct vcpu *v, struct x86_event *info) return hvm_funcs.get_pending_event(v, info); } +static void hvm_vm_event_set_registers(struct vcpu *v) +{ + ASSERT(v == current); + + if ( v->arch.vm_event->set_gprs ) + { + struct cpu_user_regs *regs = guest_cpu_user_regs(); + + regs->rax = v->arch.vm_event->gprs.rax; + regs->rbx = v->arch.vm_event->gprs.rbx; + regs->rcx = v->arch.vm_event->gprs.rcx; + regs->rdx = v->arch.vm_event->gprs.rdx; + regs->rsp = v->arch.vm_event->gprs.rsp; + regs->rbp = v->arch.vm_event->gprs.rbp; + regs->rsi = v->arch.vm_event->gprs.rsi; + regs->rdi = v->arch.vm_event->gprs.rdi; + + regs->r8 = v->arch.vm_event->gprs.r8; + regs->r9 = v->arch.vm_event->gprs.r9; + regs->r10 = v->arch.vm_event->gprs.r10; + regs->r11 = v->arch.vm_event->gprs.r11; + regs->r12 = v->arch.vm_event->gprs.r12; + regs->r13 = v->arch.vm_event->gprs.r13; + regs->r14 = v->arch.vm_event->gprs.r14; + regs->r15 = v->arch.vm_event->gprs.r15; + + regs->rflags = v->arch.vm_event->gprs.rflags; + regs->rip = v->arch.vm_event->gprs.rip; + + v->arch.vm_event->set_gprs = 0; + } +} + void hvm_do_resume(struct vcpu *v) { check_wakeup_from_wait(); @@ -487,6 +520,8 @@ void hvm_do_resume(struct vcpu *v) { struct monitor_write_data *w = &v->arch.vm_event->write_data; + hvm_vm_event_set_registers(v); + if ( unlikely(v->arch.vm_event->emulate_flags) ) { enum emul_kind kind = EMUL_KIND_NORMAL; diff --git a/xen/arch/x86/vm_event.c b/xen/arch/x86/vm_event.c index 502ccc2..f66780a 100644 --- a/xen/arch/x86/vm_event.c +++ b/xen/arch/x86/vm_event.c @@ -113,26 +113,8 @@ void vm_event_set_registers(struct vcpu *v, vm_event_response_t *rsp) { ASSERT(atomic_read(&v->vm_event_pause_count)); - v->arch.user_regs.rax = rsp->data.regs.x86.rax; - v->arch.user_regs.rbx = rsp->data.regs.x86.rbx; - v->arch.user_regs.rcx = rsp->data.regs.x86.rcx; - v->arch.user_regs.rdx = rsp->data.regs.x86.rdx; - v->arch.user_regs.rsp = rsp->data.regs.x86.rsp; - v->arch.user_regs.rbp = rsp->data.regs.x86.rbp; - v->arch.user_regs.rsi = rsp->data.regs.x86.rsi; - v->arch.user_regs.rdi = rsp->data.regs.x86.rdi; - - v->arch.user_regs.r8 = rsp->data.regs.x86.r8; - v->arch.user_regs.r9 = rsp->data.regs.x86.r9; - v->arch.user_regs.r10 = rsp->data.regs.x86.r10; - v->arch.user_regs.r11 = rsp->data.regs.x86.r11; - v->arch.user_regs.r12 = rsp->data.regs.x86.r12; - v->arch.user_regs.r13 = rsp->data.regs.x86.r13; - v->arch.user_regs.r14 = rsp->data.regs.x86.r14; - v->arch.user_regs.r15 = rsp->data.regs.x86.r15; - - v->arch.user_regs.rflags = rsp->data.regs.x86.rflags; - v->arch.user_regs.rip = rsp->data.regs.x86.rip; + v->arch.vm_event->gprs = rsp->data.regs.x86; + v->arch.vm_event->set_gprs = 1; } void vm_event_monitor_next_interrupt(struct vcpu *v) diff --git a/xen/common/vm_event.c b/xen/common/vm_event.c index 0fe9a53..498749b 100644 --- a/xen/common/vm_event.c +++ b/xen/common/vm_event.c @@ -357,6 +357,13 @@ void vm_event_resume(struct domain *d, struct vm_event_domain *ved) { vm_event_response_t rsp; + /* + * vm_event_resume() runs either from XEN_DOMCTL_VM_EVENT_OP_*, or + * EVTCHN_send from the introspection consumer. Both contexts are + * guaranteed not to be the subject of vm_event responses. + */ + ASSERT(d != current->domain); + /* Pull all responses off the ring. */ while ( vm_event_get_response(d, ved, &rsp) ) { @@ -375,13 +382,6 @@ void vm_event_resume(struct domain *d, struct vm_event_domain *ved) v = d->vcpu[rsp.vcpu_id]; /* - * Make sure the vCPU state has been synchronized for the custom - * handlers. - */ - if ( atomic_read(&v->vm_event_pause_count) ) - sync_vcpu_execstate(v); - - /* * In some cases the response type needs extra handling, so here * we call the appropriate handlers. */ diff --git a/xen/include/asm-x86/vm_event.h b/xen/include/asm-x86/vm_event.h index ca73f99..f703170 100644 --- a/xen/include/asm-x86/vm_event.h +++ b/xen/include/asm-x86/vm_event.h @@ -32,6 +32,8 @@ struct arch_vm_event { struct vm_event_emul_insn_data insn; } emul; struct monitor_write_data write_data; + struct vm_event_regs_x86 gprs; + bool_t set_gprs; }; int vm_event_init_domain(struct domain *d);