|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH V5 1/3] xen/mem_access: Support for memory-content hiding
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@xxxxxxxxxxxxxxx>
---
Changes since V4:
- Rebased the patch to take into account Tamas' "x86/vm_event:
toggle singlestep from vm_event response".
- Renamed MEM_ACCESS_EMULATE to VM_EVENT_FLAG_EMULATE in stale
comment in vm_event.h.
- Factored out common code setting the read data in emulate.c.
- Made sure the x86-specific code doesn't leak in the common
code (added two new functions to the x86 and ARM vm_event.c
files).
---
tools/tests/xen-access/xen-access.c | 2 +-
xen/arch/x86/domain.c | 2 +
xen/arch/x86/hvm/emulate.c | 106 ++++++++++++++++++++++++++++++++++-
xen/arch/x86/hvm/event.c | 50 ++++++++---------
xen/arch/x86/mm/p2m.c | 92 +++++++++++++++++-------------
xen/arch/x86/vm_event.c | 30 ++++++++++
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, 275 insertions(+), 78 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..6596408 100644
--- a/xen/arch/x86/domain.c
+++ b/xen/arch/x86/domain.c
@@ -511,6 +511,8 @@ int vcpu_initialise(struct vcpu *v)
void vcpu_destroy(struct vcpu *v)
{
+ xfree(v->arch.vm_event.emul_read_data);
+
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..30def25 100644
--- a/xen/arch/x86/hvm/emulate.c
+++ b/xen/arch/x86/hvm/emulate.c
@@ -67,6 +67,27 @@ static int null_write(const struct hvm_io_handler *handler,
return X86EMUL_OKAY;
}
+static int set_context_data(void *buffer, unsigned int bytes)
+{
+ struct vcpu *curr = current;
+
+ if ( !curr->arch.vm_event.emul_read_data )
+ return X86EMUL_UNHANDLEABLE;
+ else
+ {
+ unsigned int safe_bytes =
+ min(bytes, curr->arch.vm_event.emul_read_data->size);
+
+ if ( safe_bytes )
+ memcpy(buffer, curr->arch.vm_event.emul_read_data->data,
+ safe_bytes);
+
+ memset(buffer + safe_bytes, 0, bytes - safe_bytes);
+ }
+
+ return X86EMUL_OKAY;
+}
+
static const struct hvm_io_ops null_ops = {
.read = null_read,
.write = null_write
@@ -771,6 +792,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 +990,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 +1043,36 @@ 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 )
+ goto out;
+
+ rc = hvmemul_do_pio_buffer(dst_port, bytes, IOREQ_WRITE, buf);
+
+out:
+ xfree(buf);
+
+ return rc;
+}
+
static int hvmemul_rep_outs(
enum x86_segment src_seg,
unsigned long src_offset,
@@ -1021,6 +1089,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);
@@ -1133,7 +1205,20 @@ static int hvmemul_rep_movs(
*/
rc = hvm_copy_from_guest_phys(buf, sgpa, bytes);
if ( rc == HVMCOPY_okay )
+ {
+ if ( unlikely(hvmemul_ctxt->set_context) )
+ {
+ rc = set_context_data(buf, bytes);
+
+ if ( rc != X86EMUL_OKAY)
+ {
+ xfree(buf);
+ return rc;
+ }
+ }
+
rc = hvm_copy_to_guest_phys(dgpa, buf, bytes);
+ }
xfree(buf);
@@ -1292,7 +1377,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 +1769,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 +1777,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 +1821,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..0515161 100644
--- a/xen/arch/x86/vm_event.c
+++ b/xen/arch/x86/vm_event.c
@@ -23,6 +23,36 @@
#include <xen/sched.h>
#include <asm/hvm/hvm.h>
+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;
+}
+
+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);
--
1.7.9.5
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |