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.read.size);
- memcpy(buffer, curr->arch.vm_event->emul_read_data.data, safe_size);
+ memcpy(buffer, curr->arch.vm_event->emul.read.data, safe_size);
memset(buffer + safe_size, 0, size - safe_size);
return X86EMUL_OKAY;
}
return rc;
}
-void hvm_mem_access_emulate_one(enum emul_kind kind, unsigned int trapnr,
+void hvm_emulate_one_vm_event(enum emul_kind kind, unsigned int trapnr,
unsigned int errcode)
{
struct hvm_emulate_ctxt ctx = {{ 0 }};
case EMUL_KIND_NOWRITE:
rc = hvm_emulate_one_no_write(&ctx);
break;
- case EMUL_KIND_SET_CONTEXT:
- ctx.set_context = 1;
- /* Intentional fall-through. */
+ case EMUL_KIND_SET_CONTEXT_INSN: {
+ struct vcpu *curr = current;
+ struct hvm_vcpu_io *vio = &curr->arch.hvm_vcpu.hvm_io;
+
+ BUILD_BUG_ON(sizeof(vio->mmio_insn) !=
+ sizeof(curr->arch.vm_event->emul.insn.data));
+ ASSERT(!vio->mmio_insn_bytes);
+
+ /*
+ * Stash insn buffer into mmio buffer here instead of ctx
+ * to avoid having to add more logic to hvm_emulate_one.
+ */
+ vio->mmio_insn_bytes = sizeof(vio->mmio_insn);
+ memcpy(vio->mmio_insn, curr->arch.vm_event->emul.insn.data,
+ vio->mmio_insn_bytes);
+ }
+ /* Fall-through */
default:
+ ctx.set_context = (kind == EMUL_KIND_SET_CONTEXT_DATA);
rc = hvm_emulate_one(&ctx);
}
{
enum emul_kind kind = EMUL_KIND_NORMAL;
+ /*
+ * Please observ the order here to match the flag descriptions
+ * provided in public/vm_event.h
+ */
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;
+ else if ( v->arch.vm_event->emulate_flags &
+ VM_EVENT_FLAG_SET_EMUL_INSN_DATA )
+ kind = EMUL_KIND_SET_CONTEXT_INSN;
- hvm_mem_access_emulate_one(kind, TRAP_invalid_op,
- HVM_DELIVER_NO_ERROR_CODE);
+ hvm_emulate_one_vm_event(kind, TRAP_invalid_op,
+ HVM_DELIVER_NO_ERROR_CODE);
v->arch.vm_event->emulate_flags = 0;
}
if ( p2m_mem_access_emulate_check(v, rsp) )
{
if ( rsp->flags & VM_EVENT_FLAG_SET_EMUL_READ_DATA )
- v->arch.vm_event->emul_read_data = rsp->data.emul_read_data;
+ v->arch.vm_event->emul.read = rsp->data.emul.read;
v->arch.vm_event->emulate_flags = rsp->flags;
}
break;
+
+ case VM_EVENT_REASON_SOFTWARE_BREAKPOINT:
+ if ( rsp->flags & VM_EVENT_FLAG_SET_EMUL_INSN_DATA )
+ {
+ v->arch.vm_event->emul.insn = rsp->data.emul.insn;
+ v->arch.vm_event->emulate_flags = rsp->flags;
+ }
+ break;
+
default:
break;
};
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(
struct hvm_emulate_ctxt *hvmemul_ctxt);
int hvm_emulate_one_no_write(
struct hvm_emulate_ctxt *hvmemul_ctxt);
-void hvm_mem_access_emulate_one(enum emul_kind kind,
+void hvm_emulate_one_vm_event(enum emul_kind kind,
unsigned int trapnr,
unsigned int errcode);
void hvm_emulate_prepare(
*/
struct arch_vm_event {
uint32_t emulate_flags;
- struct vm_event_emul_read_data emul_read_data;
+ union {
+ struct vm_event_emul_read_data read;
+ struct vm_event_emul_insn_data insn;
+ } emul;
struct monitor_write_data write_data;
};
* 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 does not take presedence if combined with
+ * VM_EVENT_FLAG_EMULATE_NOWRITE or VM_EVENT_FLAG_SET_EMUL_READ_DATA, (i.e.
+ * if any of those flags are set, only those will be honored).
+ */
+#define VM_EVENT_FLAG_SET_EMUL_INSN_DATA (1 << 9)
/*
* Reasons for the vm event request
uint8_t data[sizeof(struct vm_event_regs_x86) - sizeof(uint32_t)];
};
+struct vm_event_emul_insn_data {
+ uint8_t data[16]; /* Has to be completely filled */
+};
+
typedef struct vm_event_st {
uint32_t version; /* VM_EVENT_INTERFACE_VERSION */
uint32_t flags; /* VM_EVENT_FLAG_* */
struct vm_event_regs_arm arm;
} regs;
- struct vm_event_emul_read_data emul_read_data;
+ union {
+ struct vm_event_emul_read_data read;
+ struct vm_event_emul_insn_data insn;
+ } emul;
} data;
} vm_event_request_t, vm_event_response_t;