From: George Dunlap <george.dunlap@eu.citrix.com>
To: Razvan Cojocaru <rcojocaru@bitdefender.com>, xen-devel@lists.xen.org
Cc: kevin.tian@intel.com, keir@xen.org, eddie.dong@intel.com,
stefano.stabellini@eu.citrix.com, jun.nakajima@intel.com,
andrew.cooper3@citrix.com, ian.jackson@eu.citrix.com,
Aravind.Gopalakrishnan@amd.com, jbeulich@suse.com,
tlengyel@novetta.com, wei.liu2@citrix.com,
boris.ostrovsky@oracle.com, suravee.suthikulpanit@amd.com,
ian.campbell@citrix.com
Subject: Re: [PATCH V6 1/3] xen/mem_access: Support for memory-content hiding
Date: Wed, 15 Jul 2015 11:10:49 +0100 [thread overview]
Message-ID: <55A631A9.9060001@eu.citrix.com> (raw)
In-Reply-To: <1436949949-4628-2-git-send-email-rcojocaru@bitdefender.com>
On 07/15/2015 09:45 AM, Razvan Cojocaru wrote:
> This patch adds support for memory-content hiding, by modifying the
> value returned by emulated instructions that read certain memory
> addresses that contain sensitive data. The patch only applies to
> cases where VM_FLAG_ACCESS_EMULATE has been set to a vm_event
> response.
>
> Signed-off-by: Razvan Cojocaru <rcojocaru@bitdefender.com>
> Acked-by: Tamas K Lengyel <tlengyel@novetta.com>
BTW I've looked at an earlier version of this and acked it, and I
haven't seen any changes I want to review; so when the rest of it is
acked/reviewed I'll take another look through and send my ack.
-George
>
> ---
> Changes since V5:
> - Renamed set_context_data()'s bytes parameter to size.
> - Inverted if() condition in set_context_data().
> - Removed memcpy() conditional from set_context_data().
> - Removed label from hvmemul_rep_outs_set_context().
> - Now bypassing hvm_copy_from_guest_phys() in hvmemul_rep_movs() if
> hvmemul_ctxt->set_context is true.
> - Fixed for_each_vcpu() coding style (blank before the opening
> parenthesis).
> - Added comments about the serialization status of
> vm_event_init_domain() and vm_event_cleanup_domain().
> - Setting v->arch.vm_event.emul_read_data to NULL after xfree() in
> vcpu_destroy() for safety.
> ---
> tools/tests/xen-access/xen-access.c | 2 +-
> xen/arch/x86/domain.c | 3 +
> xen/arch/x86/hvm/emulate.c | 117 ++++++++++++++++++++++++++++++++---
> xen/arch/x86/hvm/event.c | 50 +++++++--------
> xen/arch/x86/mm/p2m.c | 92 +++++++++++++++------------
> xen/arch/x86/vm_event.c | 35 +++++++++++
> xen/common/vm_event.c | 8 +++
> xen/include/asm-arm/vm_event.h | 13 ++++
> xen/include/asm-x86/domain.h | 1 +
> xen/include/asm-x86/hvm/emulate.h | 10 ++-
> xen/include/asm-x86/vm_event.h | 4 ++
> xen/include/public/vm_event.h | 35 ++++++++---
> 12 files changed, 287 insertions(+), 83 deletions(-)
>
> diff --git a/tools/tests/xen-access/xen-access.c b/tools/tests/xen-access/xen-access.c
> index 12ab921..e6ca9ba 100644
> --- a/tools/tests/xen-access/xen-access.c
> +++ b/tools/tests/xen-access/xen-access.c
> @@ -530,7 +530,7 @@ int main(int argc, char *argv[])
> break;
> case VM_EVENT_REASON_SOFTWARE_BREAKPOINT:
> printf("Breakpoint: rip=%016"PRIx64", gfn=%"PRIx64" (vcpu %d)\n",
> - req.regs.x86.rip,
> + req.data.regs.x86.rip,
> req.u.software_breakpoint.gfn,
> req.vcpu_id);
>
> diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c
> index 34ecd7c..1ef9fad 100644
> --- a/xen/arch/x86/domain.c
> +++ b/xen/arch/x86/domain.c
> @@ -511,6 +511,9 @@ int vcpu_initialise(struct vcpu *v)
>
> void vcpu_destroy(struct vcpu *v)
> {
> + xfree(v->arch.vm_event.emul_read_data);
> + v->arch.vm_event.emul_read_data = NULL;
> +
> if ( is_pv_32bit_vcpu(v) )
> {
> free_compat_arg_xlat(v);
> diff --git a/xen/arch/x86/hvm/emulate.c b/xen/arch/x86/hvm/emulate.c
> index 795321c..2766919 100644
> --- a/xen/arch/x86/hvm/emulate.c
> +++ b/xen/arch/x86/hvm/emulate.c
> @@ -67,6 +67,24 @@ static int null_write(const struct hvm_io_handler *handler,
> return X86EMUL_OKAY;
> }
>
> +static int set_context_data(void *buffer, unsigned int size)
> +{
> + struct vcpu *curr = current;
> +
> + if ( curr->arch.vm_event.emul_read_data )
> + {
> + unsigned int safe_size =
> + min(size, curr->arch.vm_event.emul_read_data->size);
> +
> + memcpy(buffer, curr->arch.vm_event.emul_read_data->data, safe_size);
> + memset(buffer + safe_size, 0, size - safe_size);
> + }
> + else
> + return X86EMUL_UNHANDLEABLE;
> +
> + return X86EMUL_OKAY;
> +}
> +
> static const struct hvm_io_ops null_ops = {
> .read = null_read,
> .write = null_write
> @@ -771,6 +789,12 @@ static int hvmemul_read(
> unsigned int bytes,
> struct x86_emulate_ctxt *ctxt)
> {
> + struct hvm_emulate_ctxt *hvmemul_ctxt =
> + container_of(ctxt, struct hvm_emulate_ctxt, ctxt);
> +
> + if ( unlikely(hvmemul_ctxt->set_context) )
> + return set_context_data(p_data, bytes);
> +
> return __hvmemul_read(
> seg, offset, p_data, bytes, hvm_access_read,
> container_of(ctxt, struct hvm_emulate_ctxt, ctxt));
> @@ -963,6 +987,17 @@ static int hvmemul_cmpxchg(
> unsigned int bytes,
> struct x86_emulate_ctxt *ctxt)
> {
> + struct hvm_emulate_ctxt *hvmemul_ctxt =
> + container_of(ctxt, struct hvm_emulate_ctxt, ctxt);
> +
> + if ( unlikely(hvmemul_ctxt->set_context) )
> + {
> + int rc = set_context_data(p_new, bytes);
> +
> + if ( rc != X86EMUL_OKAY )
> + return rc;
> + }
> +
> /* Fix this in case the guest is really relying on r-m-w atomicity. */
> return hvmemul_write(seg, offset, p_new, bytes, ctxt);
> }
> @@ -1005,6 +1040,38 @@ static int hvmemul_rep_ins(
> !!(ctxt->regs->eflags & X86_EFLAGS_DF), gpa);
> }
>
> +static int hvmemul_rep_outs_set_context(
> + enum x86_segment src_seg,
> + unsigned long src_offset,
> + uint16_t dst_port,
> + unsigned int bytes_per_rep,
> + unsigned long *reps,
> + struct x86_emulate_ctxt *ctxt)
> +{
> + unsigned int bytes = *reps * bytes_per_rep;
> + char *buf;
> + int rc;
> +
> + buf = xmalloc_array(char, bytes);
> +
> + if ( buf == NULL )
> + return X86EMUL_UNHANDLEABLE;
> +
> + rc = set_context_data(buf, bytes);
> +
> + if ( rc != X86EMUL_OKAY )
> + {
> + xfree(buf);
> + return rc;
> + }
> +
> + rc = hvmemul_do_pio_buffer(dst_port, bytes, IOREQ_WRITE, buf);
> +
> + xfree(buf);
> +
> + return rc;
> +}
> +
> static int hvmemul_rep_outs(
> enum x86_segment src_seg,
> unsigned long src_offset,
> @@ -1021,6 +1088,10 @@ static int hvmemul_rep_outs(
> p2m_type_t p2mt;
> int rc;
>
> + if ( unlikely(hvmemul_ctxt->set_context) )
> + return hvmemul_rep_outs_set_context(src_seg, src_offset, dst_port,
> + bytes_per_rep, reps, ctxt);
> +
> rc = hvmemul_virtual_to_linear(
> src_seg, src_offset, bytes_per_rep, reps, hvm_access_read,
> hvmemul_ctxt, &addr);
> @@ -1127,11 +1198,26 @@ static int hvmemul_rep_movs(
> if ( buf == NULL )
> return X86EMUL_UNHANDLEABLE;
>
> - /*
> - * We do a modicum of checking here, just for paranoia's sake and to
> - * definitely avoid copying an unitialised buffer into guest address space.
> - */
> - rc = hvm_copy_from_guest_phys(buf, sgpa, bytes);
> + if ( unlikely(hvmemul_ctxt->set_context) )
> + {
> + rc = set_context_data(buf, bytes);
> +
> + if ( rc != X86EMUL_OKAY)
> + {
> + xfree(buf);
> + return rc;
> + }
> +
> + rc = HVMCOPY_okay;
> + }
> + else
> + /*
> + * We do a modicum of checking here, just for paranoia's sake and to
> + * definitely avoid copying an unitialised buffer into guest address
> + * space.
> + */
> + rc = hvm_copy_from_guest_phys(buf, sgpa, bytes);
> +
> if ( rc == HVMCOPY_okay )
> rc = hvm_copy_to_guest_phys(dgpa, buf, bytes);
>
> @@ -1292,7 +1378,14 @@ static int hvmemul_read_io(
> unsigned long *val,
> struct x86_emulate_ctxt *ctxt)
> {
> + struct hvm_emulate_ctxt *hvmemul_ctxt =
> + container_of(ctxt, struct hvm_emulate_ctxt, ctxt);
> +
> *val = 0;
> +
> + if ( unlikely(hvmemul_ctxt->set_context) )
> + return set_context_data(val, bytes);
> +
> return hvmemul_do_pio_buffer(port, bytes, IOREQ_READ, val);
> }
>
> @@ -1677,7 +1770,7 @@ int hvm_emulate_one_no_write(
> return _hvm_emulate_one(hvmemul_ctxt, &hvm_emulate_ops_no_write);
> }
>
> -void hvm_mem_access_emulate_one(bool_t nowrite, unsigned int trapnr,
> +void hvm_mem_access_emulate_one(enum emul_kind kind, unsigned int trapnr,
> unsigned int errcode)
> {
> struct hvm_emulate_ctxt ctx = {{ 0 }};
> @@ -1685,10 +1778,17 @@ void hvm_mem_access_emulate_one(bool_t nowrite, unsigned int trapnr,
>
> hvm_emulate_prepare(&ctx, guest_cpu_user_regs());
>
> - if ( nowrite )
> + switch ( kind )
> + {
> + case EMUL_KIND_NOWRITE:
> rc = hvm_emulate_one_no_write(&ctx);
> - else
> + break;
> + case EMUL_KIND_SET_CONTEXT:
> + ctx.set_context = 1;
> + /* Intentional fall-through. */
> + default:
> rc = hvm_emulate_one(&ctx);
> + }
>
> switch ( rc )
> {
> @@ -1722,6 +1822,7 @@ 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_get_seg_reg(x86_seg_cs, hvmemul_ctxt);
> hvmemul_get_seg_reg(x86_seg_ss, hvmemul_ctxt);
> }
> diff --git a/xen/arch/x86/hvm/event.c b/xen/arch/x86/hvm/event.c
> index 53b9ca4..5341937 100644
> --- a/xen/arch/x86/hvm/event.c
> +++ b/xen/arch/x86/hvm/event.c
> @@ -30,31 +30,31 @@ static void hvm_event_fill_regs(vm_event_request_t *req)
> const struct cpu_user_regs *regs = guest_cpu_user_regs();
> const struct vcpu *curr = current;
>
> - req->regs.x86.rax = regs->eax;
> - req->regs.x86.rcx = regs->ecx;
> - req->regs.x86.rdx = regs->edx;
> - req->regs.x86.rbx = regs->ebx;
> - req->regs.x86.rsp = regs->esp;
> - req->regs.x86.rbp = regs->ebp;
> - req->regs.x86.rsi = regs->esi;
> - req->regs.x86.rdi = regs->edi;
> -
> - req->regs.x86.r8 = regs->r8;
> - req->regs.x86.r9 = regs->r9;
> - req->regs.x86.r10 = regs->r10;
> - req->regs.x86.r11 = regs->r11;
> - req->regs.x86.r12 = regs->r12;
> - req->regs.x86.r13 = regs->r13;
> - req->regs.x86.r14 = regs->r14;
> - req->regs.x86.r15 = regs->r15;
> -
> - req->regs.x86.rflags = regs->eflags;
> - req->regs.x86.rip = regs->eip;
> -
> - req->regs.x86.msr_efer = curr->arch.hvm_vcpu.guest_efer;
> - req->regs.x86.cr0 = curr->arch.hvm_vcpu.guest_cr[0];
> - req->regs.x86.cr3 = curr->arch.hvm_vcpu.guest_cr[3];
> - req->regs.x86.cr4 = curr->arch.hvm_vcpu.guest_cr[4];
> + req->data.regs.x86.rax = regs->eax;
> + req->data.regs.x86.rcx = regs->ecx;
> + req->data.regs.x86.rdx = regs->edx;
> + req->data.regs.x86.rbx = regs->ebx;
> + req->data.regs.x86.rsp = regs->esp;
> + req->data.regs.x86.rbp = regs->ebp;
> + req->data.regs.x86.rsi = regs->esi;
> + req->data.regs.x86.rdi = regs->edi;
> +
> + req->data.regs.x86.r8 = regs->r8;
> + req->data.regs.x86.r9 = regs->r9;
> + req->data.regs.x86.r10 = regs->r10;
> + req->data.regs.x86.r11 = regs->r11;
> + req->data.regs.x86.r12 = regs->r12;
> + req->data.regs.x86.r13 = regs->r13;
> + req->data.regs.x86.r14 = regs->r14;
> + req->data.regs.x86.r15 = regs->r15;
> +
> + req->data.regs.x86.rflags = regs->eflags;
> + req->data.regs.x86.rip = regs->eip;
> +
> + req->data.regs.x86.msr_efer = curr->arch.hvm_vcpu.guest_efer;
> + req->data.regs.x86.cr0 = curr->arch.hvm_vcpu.guest_cr[0];
> + req->data.regs.x86.cr3 = curr->arch.hvm_vcpu.guest_cr[3];
> + req->data.regs.x86.cr4 = curr->arch.hvm_vcpu.guest_cr[4];
> }
>
> static int hvm_event_traps(uint8_t sync, vm_event_request_t *req)
> diff --git a/xen/arch/x86/mm/p2m.c b/xen/arch/x86/mm/p2m.c
> index f180cee..6fe6387 100644
> --- a/xen/arch/x86/mm/p2m.c
> +++ b/xen/arch/x86/mm/p2m.c
> @@ -1369,49 +1369,49 @@ static void p2m_vm_event_fill_regs(vm_event_request_t *req)
> /* Architecture-specific vmcs/vmcb bits */
> hvm_funcs.save_cpu_ctxt(curr, &ctxt);
>
> - req->regs.x86.rax = regs->eax;
> - req->regs.x86.rcx = regs->ecx;
> - req->regs.x86.rdx = regs->edx;
> - req->regs.x86.rbx = regs->ebx;
> - req->regs.x86.rsp = regs->esp;
> - req->regs.x86.rbp = regs->ebp;
> - req->regs.x86.rsi = regs->esi;
> - req->regs.x86.rdi = regs->edi;
> -
> - req->regs.x86.r8 = regs->r8;
> - req->regs.x86.r9 = regs->r9;
> - req->regs.x86.r10 = regs->r10;
> - req->regs.x86.r11 = regs->r11;
> - req->regs.x86.r12 = regs->r12;
> - req->regs.x86.r13 = regs->r13;
> - req->regs.x86.r14 = regs->r14;
> - req->regs.x86.r15 = regs->r15;
> -
> - req->regs.x86.rflags = regs->eflags;
> - req->regs.x86.rip = regs->eip;
> -
> - req->regs.x86.dr7 = curr->arch.debugreg[7];
> - req->regs.x86.cr0 = ctxt.cr0;
> - req->regs.x86.cr2 = ctxt.cr2;
> - req->regs.x86.cr3 = ctxt.cr3;
> - req->regs.x86.cr4 = ctxt.cr4;
> -
> - req->regs.x86.sysenter_cs = ctxt.sysenter_cs;
> - req->regs.x86.sysenter_esp = ctxt.sysenter_esp;
> - req->regs.x86.sysenter_eip = ctxt.sysenter_eip;
> -
> - req->regs.x86.msr_efer = ctxt.msr_efer;
> - req->regs.x86.msr_star = ctxt.msr_star;
> - req->regs.x86.msr_lstar = ctxt.msr_lstar;
> + req->data.regs.x86.rax = regs->eax;
> + req->data.regs.x86.rcx = regs->ecx;
> + req->data.regs.x86.rdx = regs->edx;
> + req->data.regs.x86.rbx = regs->ebx;
> + req->data.regs.x86.rsp = regs->esp;
> + req->data.regs.x86.rbp = regs->ebp;
> + req->data.regs.x86.rsi = regs->esi;
> + req->data.regs.x86.rdi = regs->edi;
> +
> + req->data.regs.x86.r8 = regs->r8;
> + req->data.regs.x86.r9 = regs->r9;
> + req->data.regs.x86.r10 = regs->r10;
> + req->data.regs.x86.r11 = regs->r11;
> + req->data.regs.x86.r12 = regs->r12;
> + req->data.regs.x86.r13 = regs->r13;
> + req->data.regs.x86.r14 = regs->r14;
> + req->data.regs.x86.r15 = regs->r15;
> +
> + req->data.regs.x86.rflags = regs->eflags;
> + req->data.regs.x86.rip = regs->eip;
> +
> + req->data.regs.x86.dr7 = curr->arch.debugreg[7];
> + req->data.regs.x86.cr0 = ctxt.cr0;
> + req->data.regs.x86.cr2 = ctxt.cr2;
> + req->data.regs.x86.cr3 = ctxt.cr3;
> + req->data.regs.x86.cr4 = ctxt.cr4;
> +
> + req->data.regs.x86.sysenter_cs = ctxt.sysenter_cs;
> + req->data.regs.x86.sysenter_esp = ctxt.sysenter_esp;
> + req->data.regs.x86.sysenter_eip = ctxt.sysenter_eip;
> +
> + req->data.regs.x86.msr_efer = ctxt.msr_efer;
> + req->data.regs.x86.msr_star = ctxt.msr_star;
> + req->data.regs.x86.msr_lstar = ctxt.msr_lstar;
>
> hvm_get_segment_register(curr, x86_seg_fs, &seg);
> - req->regs.x86.fs_base = seg.base;
> + req->data.regs.x86.fs_base = seg.base;
>
> hvm_get_segment_register(curr, x86_seg_gs, &seg);
> - req->regs.x86.gs_base = seg.base;
> + req->data.regs.x86.gs_base = seg.base;
>
> hvm_get_segment_register(curr, x86_seg_cs, &seg);
> - req->regs.x86.cs_arbytes = seg.attr.bytes;
> + req->data.regs.x86.cs_arbytes = seg.attr.bytes;
> }
>
> void p2m_mem_access_emulate_check(struct vcpu *v,
> @@ -1466,6 +1466,10 @@ 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 )
> + *v->arch.vm_event.emul_read_data = rsp->data.emul_read_data;
> }
> }
>
> @@ -1552,9 +1556,17 @@ bool_t p2m_mem_access_check(paddr_t gpa, unsigned long gla,
>
> if ( v->arch.vm_event.emulate_flags )
> {
> - hvm_mem_access_emulate_one((v->arch.vm_event.emulate_flags &
> - VM_EVENT_FLAG_EMULATE_NOWRITE) != 0,
> - TRAP_invalid_op, HVM_DELIVER_NO_ERROR_CODE);
> + enum emul_kind kind = EMUL_KIND_NORMAL;
> +
> + if ( v->arch.vm_event.emulate_flags &
> + VM_EVENT_FLAG_SET_EMUL_READ_DATA )
> + kind = EMUL_KIND_SET_CONTEXT;
> + else if ( v->arch.vm_event.emulate_flags &
> + VM_EVENT_FLAG_EMULATE_NOWRITE )
> + kind = EMUL_KIND_NOWRITE;
> +
> + hvm_mem_access_emulate_one(kind, TRAP_invalid_op,
> + HVM_DELIVER_NO_ERROR_CODE);
>
> v->arch.vm_event.emulate_flags = 0;
> return 1;
> diff --git a/xen/arch/x86/vm_event.c b/xen/arch/x86/vm_event.c
> index c390225..ec856fb 100644
> --- a/xen/arch/x86/vm_event.c
> +++ b/xen/arch/x86/vm_event.c
> @@ -23,6 +23,41 @@
> #include <xen/sched.h>
> #include <asm/hvm/hvm.h>
>
> +/* Implicitly serialized by the domctl lock. */
> +int vm_event_init_domain(struct domain *d)
> +{
> + struct vcpu *v;
> +
> + for_each_vcpu ( d, v )
> + {
> + if ( v->arch.vm_event.emul_read_data )
> + continue;
> +
> + v->arch.vm_event.emul_read_data =
> + xzalloc(struct vm_event_emul_read_data);
> +
> + if ( !v->arch.vm_event.emul_read_data )
> + return -ENOMEM;
> + }
> +
> + return 0;
> +}
> +
> +/*
> + * Implicitly serialized by the domctl lock,
> + * or on domain cleanup paths only.
> + */
> +void vm_event_cleanup_domain(struct domain *d)
> +{
> + struct vcpu *v;
> +
> + for_each_vcpu ( d, v )
> + {
> + xfree(v->arch.vm_event.emul_read_data);
> + v->arch.vm_event.emul_read_data = NULL;
> + }
> +}
> +
> void vm_event_toggle_singlestep(struct domain *d, struct vcpu *v)
> {
> if ( !is_hvm_domain(d) || !atomic_read(&v->vm_event_pause_count) )
> diff --git a/xen/common/vm_event.c b/xen/common/vm_event.c
> index a4b9c36..0007d70 100644
> --- a/xen/common/vm_event.c
> +++ b/xen/common/vm_event.c
> @@ -64,6 +64,11 @@ static int vm_event_enable(
> vm_event_ring_lock_init(ved);
> vm_event_ring_lock(ved);
>
> + rc = vm_event_init_domain(d);
> +
> + if ( rc < 0 )
> + goto err;
> +
> rc = prepare_ring_for_helper(d, ring_gfn, &ved->ring_pg_struct,
> &ved->ring_page);
> if ( rc < 0 )
> @@ -226,6 +231,9 @@ static int vm_event_disable(struct domain *d, struct vm_event_domain *ved)
>
> destroy_ring_for_helper(&ved->ring_page,
> ved->ring_pg_struct);
> +
> + vm_event_cleanup_domain(d);
> +
> vm_event_ring_unlock(ved);
> }
>
> diff --git a/xen/include/asm-arm/vm_event.h b/xen/include/asm-arm/vm_event.h
> index a517495..20469a8 100644
> --- a/xen/include/asm-arm/vm_event.h
> +++ b/xen/include/asm-arm/vm_event.h
> @@ -23,6 +23,19 @@
> #include <xen/sched.h>
>
> static inline
> +int vm_event_init_domain(struct domain *d)
> +{
> + /* Not supported on ARM. */
> + return 0;
> +}
> +
> +static inline
> +void vm_event_cleanup_domain(struct domain *d)
> +{
> + /* Not supported on ARM. */
> +}
> +
> +static inline
> void vm_event_toggle_singlestep(struct domain *d, struct vcpu *v)
> {
> /* Not supported on ARM. */
> diff --git a/xen/include/asm-x86/domain.h b/xen/include/asm-x86/domain.h
> index 201436d..c5ad1cb 100644
> --- a/xen/include/asm-x86/domain.h
> +++ b/xen/include/asm-x86/domain.h
> @@ -512,6 +512,7 @@ struct arch_vcpu
> uint32_t emulate_flags;
> unsigned long gpa;
> unsigned long eip;
> + struct vm_event_emul_read_data *emul_read_data;
> } vm_event;
>
> };
> diff --git a/xen/include/asm-x86/hvm/emulate.h b/xen/include/asm-x86/hvm/emulate.h
> index 594be38..49134b5 100644
> --- a/xen/include/asm-x86/hvm/emulate.h
> +++ b/xen/include/asm-x86/hvm/emulate.h
> @@ -32,13 +32,21 @@ struct hvm_emulate_ctxt {
> struct hvm_trap trap;
>
> uint32_t intr_shadow;
> +
> + bool_t set_context;
> +};
> +
> +enum emul_kind {
> + EMUL_KIND_NORMAL,
> + EMUL_KIND_NOWRITE,
> + EMUL_KIND_SET_CONTEXT
> };
>
> int hvm_emulate_one(
> struct hvm_emulate_ctxt *hvmemul_ctxt);
> int hvm_emulate_one_no_write(
> struct hvm_emulate_ctxt *hvmemul_ctxt);
> -void hvm_mem_access_emulate_one(bool_t nowrite,
> +void hvm_mem_access_emulate_one(enum emul_kind kind,
> unsigned int trapnr,
> unsigned int errcode);
> void hvm_emulate_prepare(
> diff --git a/xen/include/asm-x86/vm_event.h b/xen/include/asm-x86/vm_event.h
> index 7cc3a3d..3881783 100644
> --- a/xen/include/asm-x86/vm_event.h
> +++ b/xen/include/asm-x86/vm_event.h
> @@ -22,6 +22,10 @@
>
> #include <xen/sched.h>
>
> +int vm_event_init_domain(struct domain *d);
> +
> +void vm_event_cleanup_domain(struct domain *d);
> +
> void vm_event_toggle_singlestep(struct domain *d, struct vcpu *v);
>
> #endif /* __ASM_X86_VM_EVENT_H__ */
> diff --git a/xen/include/public/vm_event.h b/xen/include/public/vm_event.h
> index c756c7c..4d89c38 100644
> --- a/xen/include/public/vm_event.h
> +++ b/xen/include/public/vm_event.h
> @@ -44,9 +44,9 @@
> * paused
> * VCPU_PAUSED in a response signals to unpause the vCPU
> */
> -#define VM_EVENT_FLAG_VCPU_PAUSED (1 << 0)
> +#define VM_EVENT_FLAG_VCPU_PAUSED (1 << 0)
> /* Flags to aid debugging vm_event */
> -#define VM_EVENT_FLAG_FOREIGN (1 << 1)
> +#define VM_EVENT_FLAG_FOREIGN (1 << 1)
> /*
> * The following flags can be set in response to a mem_access event.
> *
> @@ -54,17 +54,26 @@
> * This will allow the guest to continue execution without lifting the page
> * access restrictions.
> */
> -#define VM_EVENT_FLAG_EMULATE (1 << 2)
> +#define VM_EVENT_FLAG_EMULATE (1 << 2)
> /*
> - * Same as MEM_ACCESS_EMULATE, but with write operations or operations
> + * Same as VM_EVENT_FLAG_EMULATE, but with write operations or operations
> * potentially having side effects (like memory mapped or port I/O) disabled.
> */
> -#define VM_EVENT_FLAG_EMULATE_NOWRITE (1 << 3)
> +#define VM_EVENT_FLAG_EMULATE_NOWRITE (1 << 3)
> /*
> * Toggle singlestepping on vm_event response.
> * Requires the vCPU to be paused already (synchronous events only).
> */
> -#define VM_EVENT_FLAG_TOGGLE_SINGLESTEP (1 << 4)
> +#define VM_EVENT_FLAG_TOGGLE_SINGLESTEP (1 << 4)
> +/*
> + * Data is being sent back to the hypervisor in the event response, to be
> + * returned by the read function when emulating an instruction.
> + * This flag is only useful when combined with VM_EVENT_FLAG_EMULATE
> + * and takes precedence if combined with VM_EVENT_FLAG_EMULATE_NOWRITE
> + * (i.e. if both VM_EVENT_FLAG_EMULATE_NOWRITE and
> + * VM_EVENT_FLAG_SET_EMUL_READ_DATA are set, only the latter will be honored).
> + */
> +#define VM_EVENT_FLAG_SET_EMUL_READ_DATA (1 << 5)
>
> /*
> * Reasons for the vm event request
> @@ -194,6 +203,12 @@ struct vm_event_sharing {
> uint32_t _pad;
> };
>
> +struct vm_event_emul_read_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)];
> +};
> +
> typedef struct vm_event_st {
> uint32_t version; /* VM_EVENT_INTERFACE_VERSION */
> uint32_t flags; /* VM_EVENT_FLAG_* */
> @@ -211,8 +226,12 @@ typedef struct vm_event_st {
> } u;
>
> union {
> - struct vm_event_regs_x86 x86;
> - } regs;
> + union {
> + struct vm_event_regs_x86 x86;
> + } regs;
> +
> + struct vm_event_emul_read_data emul_read_data;
> + } data;
> } vm_event_request_t, vm_event_response_t;
>
> DEFINE_RING_TYPES(vm_event, vm_event_request_t, vm_event_response_t);
>
next prev parent reply other threads:[~2015-07-15 10:10 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-07-15 8:45 [PATCH V6 0/3] Vm_event memory introspection helpers Razvan Cojocaru
2015-07-15 8:45 ` [PATCH V6 1/3] xen/mem_access: Support for memory-content hiding Razvan Cojocaru
2015-07-15 10:10 ` George Dunlap [this message]
2015-07-15 10:21 ` Jan Beulich
2015-07-15 10:38 ` George Dunlap
2015-07-15 10:41 ` Razvan Cojocaru
2015-07-15 10:21 ` Razvan Cojocaru
2015-07-15 8:45 ` [PATCH V6 2/3] xen/vm_event: Support for guest-requested events Razvan Cojocaru
2015-07-15 8:45 ` [PATCH V6 3/3] xen/vm_event: Deny register writes if refused by vm_event reply Razvan Cojocaru
2015-07-15 10:21 ` [PATCH V6 0/3] Vm_event memory introspection helpers Wei Liu
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=55A631A9.9060001@eu.citrix.com \
--to=george.dunlap@eu.citrix.com \
--cc=Aravind.Gopalakrishnan@amd.com \
--cc=andrew.cooper3@citrix.com \
--cc=boris.ostrovsky@oracle.com \
--cc=eddie.dong@intel.com \
--cc=ian.campbell@citrix.com \
--cc=ian.jackson@eu.citrix.com \
--cc=jbeulich@suse.com \
--cc=jun.nakajima@intel.com \
--cc=keir@xen.org \
--cc=kevin.tian@intel.com \
--cc=rcojocaru@bitdefender.com \
--cc=stefano.stabellini@eu.citrix.com \
--cc=suravee.suthikulpanit@amd.com \
--cc=tlengyel@novetta.com \
--cc=wei.liu2@citrix.com \
--cc=xen-devel@lists.xen.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.