From patchwork Fri Sep 9 15:41:25 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tamas Lengyel X-Patchwork-Id: 9323865 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 AF993607D3 for ; Fri, 9 Sep 2016 15:44:31 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id A016B29F59 for ; Fri, 9 Sep 2016 15:44:31 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 9466829F5B; Fri, 9 Sep 2016 15:44: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.1 required=2.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_MED,T_DKIM_INVALID 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 A5C7229F59 for ; Fri, 9 Sep 2016 15:44:28 +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 1biNvy-0007zI-BI; Fri, 09 Sep 2016 15:41:42 +0000 Received: from mail6.bemta6.messagelabs.com ([193.109.254.103]) by lists.xenproject.org with esmtp (Exim 4.84_2) (envelope-from ) id 1biNvx-0007zC-Ok for xen-devel@lists.xenproject.org; Fri, 09 Sep 2016 15:41:42 +0000 Received: from [193.109.254.147] by server-5.bemta-6.messagelabs.com id 1E/DE-29563-538D2D75; Fri, 09 Sep 2016 15:41:41 +0000 X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFupnkeJIrShJLcpLzFFi42K5GHrgiK7JjUv hBr/XC1l83zKZyYHR4/CHKywBjFGsmXlJ+RUJrBmb3lxiLJgQU3H74Q7GBsZOry5GLg4hgRmM Elu3PWQEcVgE3rBITPnRwgLiSAi8Y5HY+vEeWxcjJ5ATI3F06kJGCLtC4sCuN+wgtpCApsTBD WeYIUZNYJLo2bSSGSTBJmAkcfVqD1iziICSxL1Vk5lAipgFTjNLvDrVAVYkLOAkMfnMRrBJLA KqEpNmfmTtYuTg4BWwl3g9oQ5imZzEpW1fmCcw8i1gZFjFqFGcWlSWWqRrZKiXVJSZnlGSm5i Zo2toYKaXm1pcnJiempOYVKyXnJ+7iREYLAxAsIPxz7KAQ4ySHExKoryb9l4KF+JLyk+pzEgs zogvKs1JLT7EKMPBoSTB630dKCdYlJqeWpGWmQMMW5i0BAePkggvF0iat7ggMbc4Mx0idYrRm GPL72trmTi2Tb23lkmIJS8/L1VKnNcCpFQApDSjNA9uECyeLjHKSgnzMgKdJsRTkFqUm1mCKv +KUZyDUUmYNxVkCk9mXgncvldApzABnSJ06jzIKSWJCCmpBkZ5sad2qcf6O1Z0qaglh9T8TeW S9O2XW36Z47xcc/HEGQU+LwK0t397HbbS9G7Z25l8c248s4u7rLFb4pep5ocDCuXflfWiznvt 4LNY/k0nJsix8dajNJcvbOmfxDfUcJ/+plqjZ7Y24E9DyeKdS0Ldi+3P17780PeyaurT1tCXi /J82GRi3yqxFGckGmoxFxUnAgClePH3ogIAAA== X-Env-Sender: tamas.lengyel@zentific.com X-Msg-Ref: server-12.tower-27.messagelabs.com!1473435698!58207421!1 X-Originating-IP: [209.85.192.196] X-SpamReason: No, hits=0.0 required=7.0 tests= X-StarScan-Received: X-StarScan-Version: 8.84; banners=-,-,- X-VirusChecked: Checked Received: (qmail 36260 invoked from network); 9 Sep 2016 15:41:40 -0000 Received: from mail-pf0-f196.google.com (HELO mail-pf0-f196.google.com) (209.85.192.196) by server-12.tower-27.messagelabs.com with AES128-GCM-SHA256 encrypted SMTP; 9 Sep 2016 15:41:40 -0000 Received: by mail-pf0-f196.google.com with SMTP id x24so4176539pfa.3 for ; Fri, 09 Sep 2016 08:41:39 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=zentific-com.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id; bh=HJ2WYtu7w9afxtXOgPrmCU9t+SwbrUmZeeVcT/d643I=; b=IilGQ/Z40RBtkYWUR3fVk4deZjmLg4A3pxx0yp2tZ0WrIvLaVRFoWbv88BK1WGG4vh JMKiODqOnlnZAfwniRt8Am3NoCxEZHEGf5UX3VJnhPzFmoqRNpfknVf+i24FlMX+6lgT V5/wybE8SnSZnm6n85GKVah1CsTVHew4+NxHzBEw0J7wHaLde9QFuRqQcVcurZhweKA0 AJUfW7wZ3cHmUTFIG6bbz/sP4rqj8vSFmZvPfNBcqHpeiTkxBNopmo8lR2QgIBjkxr02 kqvVeygwlvkOCnkCc1ER3fd/5661uILNPStfctuKSl0t9zkZ5fpepP4wLgkH42XmDk5E ca0Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=HJ2WYtu7w9afxtXOgPrmCU9t+SwbrUmZeeVcT/d643I=; b=EAa82Oz28RjkKfZlxYNLOD22NOIaWJWgdaa9twuJYxBi28ezv07dQlBTu2Ai5ETuz6 GPQWJ+GLsXb2DXqKLLSr4zP20IF8e+cbwc47pVM3ltmo+dMxzkLjXhMKVJ73xbJwn5op YiBg/4lrCnZEEomfGBMrTYqV+zJ74nSCyHl9DMtOF/MsjJN646Ck7XYvzMfUEoiNQ/Q9 dLrTkELrjgKJ96IS2oMFdXvaIoyJ8AbKWvsDbYpAFT/o6JnpPJRvoP8J464M8iP31UAs cLK9bDldXzVbg3WI70+XqrLS8JEEvNLBhMkUX9Fgkg1sJ2BzefB7OdYqHJDKO1hecmN9 rU9w== X-Gm-Message-State: AE9vXwMf58FEASCPpC+ShhHwWxLpGIzZ4K+deaX4eNtr6FMftMOs6/oUofJiOgxBDxPUcA== X-Received: by 10.98.34.66 with SMTP id i63mr7726984pfi.130.1473435698311; Fri, 09 Sep 2016 08:41:38 -0700 (PDT) Received: from l1.lan (c-73-14-35-59.hsd1.co.comcast.net. [73.14.35.59]) by smtp.gmail.com with ESMTPSA id ci9sm710445pad.34.2016.09.09.08.41.30 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 09 Sep 2016 08:41:37 -0700 (PDT) From: Tamas K Lengyel To: xen-devel@lists.xenproject.org Date: Fri, 9 Sep 2016 09:41:25 -0600 Message-Id: <20160909154125.15976-1-tamas.lengyel@zentific.com> X-Mailer: git-send-email 2.9.3 Cc: Kevin Tian , Tamas K Lengyel , Jan Beulich , Razvan Cojocaru , George Dunlap , Tamas K Lengyel , Julien Grall , Paul Durrant , Stefano Stabellini , Jun Nakajima , Andrew Cooper Subject: [Xen-devel] [RFC] x86/vm_event: Allow returning i-cache for emulation 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 When emulating instructions the emulator maintains a small i-cache fetched from the guest memory. Under certain scenarios this memory region may contain instructions that a monitor subscriber would prefer to hide, namely INT3, and instead would prefer to emulate a different instruction in-place. This patch extends the vm_event interface to allow returning this i-cache via the vm_event response. Signed-off-by: Tamas K Lengyel --- Cc: Paul Durrant Cc: Jan Beulich Cc: Andrew Cooper Cc: Jun Nakajima Cc: Kevin Tian Cc: George Dunlap Cc: Razvan Cojocaru Cc: Tamas K Lengyel Cc: Stefano Stabellini Cc: Julien Grall --- xen/arch/x86/hvm/emulate.c | 47 +++++++++++++++++++++++++-------------- xen/arch/x86/hvm/hvm.c | 2 +- xen/arch/x86/hvm/vmx/vmx.c | 1 + xen/arch/x86/mm/p2m.c | 7 ++++-- xen/arch/x86/vm_event.c | 10 +++++++++ xen/common/vm_event.c | 5 ++++- xen/include/asm-arm/vm_event.h | 6 +++++ xen/include/asm-x86/hvm/emulate.h | 6 +++-- xen/include/asm-x86/vm_event.h | 4 +++- xen/include/public/vm_event.h | 11 +++++++-- 10 files changed, 73 insertions(+), 26 deletions(-) diff --git a/xen/arch/x86/hvm/emulate.c b/xen/arch/x86/hvm/emulate.c index c55ad7b..968fb7b 100644 --- a/xen/arch/x86/hvm/emulate.c +++ b/xen/arch/x86/hvm/emulate.c @@ -76,9 +76,12 @@ static int set_context_data(void *buffer, unsigned int size) if ( curr->arch.vm_event ) { unsigned int safe_size = - min(size, curr->arch.vm_event->emul_read_data.size); + min(size, curr->arch.vm_event->emul_data.size); - memcpy(buffer, curr->arch.vm_event->emul_read_data.data, safe_size); + gdprintk(XENLOG_WARNING, "Got buffer of size: %u. Request is for %u. Safe size: %u\n", + curr->arch.vm_event->emul_data.size, size, safe_size); + + memcpy(buffer, curr->arch.vm_event->emul_data.data, safe_size); memset(buffer + safe_size, 0, size - safe_size); return X86EMUL_OKAY; } @@ -825,7 +828,7 @@ static int hvmemul_read( struct hvm_emulate_ctxt *hvmemul_ctxt = container_of(ctxt, struct hvm_emulate_ctxt, ctxt); - if ( unlikely(hvmemul_ctxt->set_context) ) + if ( unlikely(hvmemul_ctxt->set_context_data) ) return set_context_data(p_data, bytes); return __hvmemul_read( @@ -1027,7 +1030,7 @@ static int hvmemul_cmpxchg( struct hvm_emulate_ctxt *hvmemul_ctxt = container_of(ctxt, struct hvm_emulate_ctxt, ctxt); - if ( unlikely(hvmemul_ctxt->set_context) ) + if ( unlikely(hvmemul_ctxt->set_context_data) ) { int rc = set_context_data(p_new, bytes); @@ -1120,7 +1123,7 @@ static int hvmemul_rep_outs( p2m_type_t p2mt; int rc; - if ( unlikely(hvmemul_ctxt->set_context) ) + if ( unlikely(hvmemul_ctxt->set_context_data) ) return hvmemul_rep_outs_set_context(src_seg, src_offset, dst_port, bytes_per_rep, reps, ctxt); @@ -1262,7 +1265,7 @@ static int hvmemul_rep_movs( if ( buf == NULL ) return X86EMUL_UNHANDLEABLE; - if ( unlikely(hvmemul_ctxt->set_context) ) + if ( unlikely(hvmemul_ctxt->set_context_data) ) { rc = set_context_data(buf, bytes); @@ -1460,7 +1463,7 @@ static int hvmemul_read_io( *val = 0; - if ( unlikely(hvmemul_ctxt->set_context) ) + if ( unlikely(hvmemul_ctxt->set_context_data) ) return set_context_data(val, bytes); return hvmemul_do_pio_buffer(port, bytes, IOREQ_READ, val); @@ -1783,7 +1786,14 @@ static int _hvm_emulate_one(struct hvm_emulate_ctxt *hvmemul_ctxt, pfec |= PFEC_user_mode; hvmemul_ctxt->insn_buf_eip = regs->eip; - if ( !vio->mmio_insn_bytes ) + + if ( unlikely(hvmemul_ctxt->set_context_insn) ) + { + memcpy(hvmemul_ctxt->insn_buf, curr->arch.vm_event->emul_data.data, + curr->arch.vm_event->emul_data.size); + hvmemul_ctxt->insn_buf_bytes = curr->arch.vm_event->emul_data.size; + } + else if ( !vio->mmio_insn_bytes ) { hvmemul_ctxt->insn_buf_bytes = hvm_get_insn_bytes(curr, hvmemul_ctxt->insn_buf) ?: @@ -1927,17 +1937,19 @@ void hvm_mem_access_emulate_one(enum emul_kind kind, unsigned int trapnr, struct hvm_emulate_ctxt ctx = {{ 0 }}; int rc; + gdprintk(XENLOG_WARNING, "memaccess emulate one called\n"); + hvm_emulate_prepare(&ctx, guest_cpu_user_regs()); - switch ( kind ) - { - case EMUL_KIND_NOWRITE: + if ( kind == EMUL_KIND_NOWRITE ) rc = hvm_emulate_one_no_write(&ctx); - break; - case EMUL_KIND_SET_CONTEXT: - ctx.set_context = 1; - /* Intentional fall-through. */ - default: + else + { + if ( kind == EMUL_KIND_SET_CONTEXT_DATA ) + ctx.set_context_data = 1; + else if ( kind == EMUL_KIND_SET_CONTEXT_INSN ) + ctx.set_context_insn = 1; + rc = hvm_emulate_one(&ctx); } @@ -1973,7 +1985,8 @@ void hvm_emulate_prepare( hvmemul_ctxt->ctxt.force_writeback = 1; hvmemul_ctxt->seg_reg_accessed = 0; hvmemul_ctxt->seg_reg_dirty = 0; - hvmemul_ctxt->set_context = 0; + hvmemul_ctxt->set_context_data = 0; + hvmemul_ctxt->set_context_insn = 0; hvmemul_get_seg_reg(x86_seg_cs, hvmemul_ctxt); hvmemul_get_seg_reg(x86_seg_ss, hvmemul_ctxt); } diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c index 2c89984..fb11f3b 100644 --- a/xen/arch/x86/hvm/hvm.c +++ b/xen/arch/x86/hvm/hvm.c @@ -481,7 +481,7 @@ void hvm_do_resume(struct vcpu *v) if ( v->arch.vm_event->emulate_flags & VM_EVENT_FLAG_SET_EMUL_READ_DATA ) - kind = EMUL_KIND_SET_CONTEXT; + kind = EMUL_KIND_SET_CONTEXT_DATA; else if ( v->arch.vm_event->emulate_flags & VM_EVENT_FLAG_EMULATE_NOWRITE ) kind = EMUL_KIND_NOWRITE; diff --git a/xen/arch/x86/hvm/vmx/vmx.c b/xen/arch/x86/hvm/vmx/vmx.c index bb7a329..41dc678 100644 --- a/xen/arch/x86/hvm/vmx/vmx.c +++ b/xen/arch/x86/hvm/vmx/vmx.c @@ -57,6 +57,7 @@ #include #include #include +#include #include static bool_t __initdata opt_force_ept; diff --git a/xen/arch/x86/mm/p2m.c b/xen/arch/x86/mm/p2m.c index 812dbf6..dfed0b3 100644 --- a/xen/arch/x86/mm/p2m.c +++ b/xen/arch/x86/mm/p2m.c @@ -1641,8 +1641,11 @@ void p2m_mem_access_emulate_check(struct vcpu *v, v->arch.vm_event->emulate_flags = violation ? rsp->flags : 0; - if ( (rsp->flags & VM_EVENT_FLAG_SET_EMUL_READ_DATA) ) - v->arch.vm_event->emul_read_data = rsp->data.emul_read_data; + if ( !!(rsp->flags & VM_EVENT_FLAG_SET_EMUL_READ_DATA) ) + { + gdprintk(XENLOG_WARNING, "Mem access emulate check setting emul read data buffer\n"); + v->arch.vm_event->emul_data = rsp->data.emul_data; + } } } diff --git a/xen/arch/x86/vm_event.c b/xen/arch/x86/vm_event.c index e938ca3..4a9327f 100644 --- a/xen/arch/x86/vm_event.c +++ b/xen/arch/x86/vm_event.c @@ -66,6 +66,16 @@ void vm_event_toggle_singlestep(struct domain *d, struct vcpu *v) hvm_toggle_singlestep(v); } +void vm_event_interrupt_emulate_check(struct vcpu *v, vm_event_response_t *rsp) +{ + if ( !!(rsp->flags & VM_EVENT_FLAG_EMULATE) && + !!(rsp->flags & VM_EVENT_FLAG_SET_EMUL_INSN_DATA) ) + { + v->arch.vm_event->emulate_flags = rsp->flags; + v->arch.vm_event->emul_data = rsp->data.emul_data; + } +} + void vm_event_register_write_resume(struct vcpu *v, vm_event_response_t *rsp) { if ( rsp->flags & VM_EVENT_FLAG_DENY ) diff --git a/xen/common/vm_event.c b/xen/common/vm_event.c index 8398af7..161d149 100644 --- a/xen/common/vm_event.c +++ b/xen/common/vm_event.c @@ -407,8 +407,11 @@ void vm_event_resume(struct domain *d, struct vm_event_domain *ved) vm_event_register_write_resume(v, &rsp); break; + case VM_EVENT_REASON_SOFTWARE_BREAKPOINT: + vm_event_interrupt_emulate_check(v, &rsp); + break; + #ifdef CONFIG_HAS_MEM_ACCESS - case VM_EVENT_REASON_MEM_ACCESS: mem_access_resume(v, &rsp); break; #endif diff --git a/xen/include/asm-arm/vm_event.h b/xen/include/asm-arm/vm_event.h index ccc4b60..e56bc78 100644 --- a/xen/include/asm-arm/vm_event.h +++ b/xen/include/asm-arm/vm_event.h @@ -40,6 +40,12 @@ static inline void vm_event_toggle_singlestep(struct domain *d, struct vcpu *v) } static inline +void vm_event_interrupt_emulate_check(struct vcpu *v, vm_event_response_t *rsp) +{ + /* Not supported on ARM. */ +} + +static inline void vm_event_register_write_resume(struct vcpu *v, vm_event_response_t *rsp) { /* Not supported on ARM. */ diff --git a/xen/include/asm-x86/hvm/emulate.h b/xen/include/asm-x86/hvm/emulate.h index 142d1b6..8e69371 100644 --- a/xen/include/asm-x86/hvm/emulate.h +++ b/xen/include/asm-x86/hvm/emulate.h @@ -33,13 +33,15 @@ struct hvm_emulate_ctxt { uint32_t intr_shadow; - bool_t set_context; + bool_t set_context_data; + bool_t set_context_insn; }; enum emul_kind { EMUL_KIND_NORMAL, EMUL_KIND_NOWRITE, - EMUL_KIND_SET_CONTEXT + EMUL_KIND_SET_CONTEXT_DATA, + EMUL_KIND_SET_CONTEXT_INSN }; int hvm_emulate_one( diff --git a/xen/include/asm-x86/vm_event.h b/xen/include/asm-x86/vm_event.h index 7e6adff..2e3f30b 100644 --- a/xen/include/asm-x86/vm_event.h +++ b/xen/include/asm-x86/vm_event.h @@ -27,7 +27,7 @@ */ struct arch_vm_event { uint32_t emulate_flags; - struct vm_event_emul_read_data emul_read_data; + struct vm_event_emul_data emul_data; struct monitor_write_data write_data; }; @@ -37,6 +37,8 @@ void vm_event_cleanup_domain(struct domain *d); void vm_event_toggle_singlestep(struct domain *d, struct vcpu *v); +void vm_event_interrupt_emulate_check(struct vcpu *v, vm_event_response_t *rsp); + void vm_event_register_write_resume(struct vcpu *v, vm_event_response_t *rsp); void vm_event_set_registers(struct vcpu *v, vm_event_response_t *rsp); diff --git a/xen/include/public/vm_event.h b/xen/include/public/vm_event.h index 99d60ea..b83b57d 100644 --- a/xen/include/public/vm_event.h +++ b/xen/include/public/vm_event.h @@ -97,6 +97,13 @@ * Requires the vCPU to be paused already (synchronous events only). */ #define VM_EVENT_FLAG_SET_REGISTERS (1 << 8) +/* + * Instruction cache is being sent back to the hypervisor in the event response + * to be used by the emulator. This flag is only useful when combined with + * VM_EVENT_FLAG_EMULATE and is incompatible with also setting + * VM_EVENT_FLAG_EMULATE_NOWRITE or VM_EVENT_FLAG_SET_EMUL_READ_DATA. + */ +#define VM_EVENT_FLAG_SET_EMUL_INSN_DATA (1 << 9) /* * Reasons for the vm event request @@ -246,7 +253,7 @@ struct vm_event_sharing { uint32_t _pad; }; -struct vm_event_emul_read_data { +struct vm_event_emul_data { uint32_t size; /* The struct is used in a union with vm_event_regs_x86. */ uint8_t data[sizeof(struct vm_event_regs_x86) - sizeof(uint32_t)]; @@ -277,7 +284,7 @@ typedef struct vm_event_st { struct vm_event_regs_x86 x86; } regs; - struct vm_event_emul_read_data emul_read_data; + struct vm_event_emul_data emul_data; } data; } vm_event_request_t, vm_event_response_t;