Commit 4d2179e1 authored by Gleb Natapov's avatar Gleb Natapov Committed by Avi Kivity

KVM: x86 emulator: handle shadowed registers outside emulator

Emulator shouldn't access vcpu directly.
Signed-off-by: default avatarGleb Natapov <gleb@redhat.com>
Signed-off-by: default avatarAvi Kivity <avi@redhat.com>
parent bdb475a3
...@@ -941,12 +941,9 @@ x86_decode_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops) ...@@ -941,12 +941,9 @@ x86_decode_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
/* we cannot decode insn before we complete previous rep insn */ /* we cannot decode insn before we complete previous rep insn */
WARN_ON(ctxt->restart); WARN_ON(ctxt->restart);
/* Shadow copy of register state. Committed on successful emulation. */
memset(c, 0, sizeof(struct decode_cache));
c->eip = ctxt->eip; c->eip = ctxt->eip;
c->fetch.start = c->fetch.end = c->eip; c->fetch.start = c->fetch.end = c->eip;
ctxt->cs_base = seg_base(ctxt, ops, VCPU_SREG_CS); ctxt->cs_base = seg_base(ctxt, ops, VCPU_SREG_CS);
memcpy(c->regs, ctxt->vcpu->arch.regs, sizeof c->regs);
switch (mode) { switch (mode) {
case X86EMUL_MODE_REAL: case X86EMUL_MODE_REAL:
...@@ -2486,16 +2483,13 @@ int emulator_task_switch(struct x86_emulate_ctxt *ctxt, ...@@ -2486,16 +2483,13 @@ int emulator_task_switch(struct x86_emulate_ctxt *ctxt,
struct decode_cache *c = &ctxt->decode; struct decode_cache *c = &ctxt->decode;
int rc; int rc;
memset(c, 0, sizeof(struct decode_cache));
c->eip = ctxt->eip; c->eip = ctxt->eip;
memcpy(c->regs, ctxt->vcpu->arch.regs, sizeof c->regs);
c->dst.type = OP_NONE; c->dst.type = OP_NONE;
rc = emulator_do_task_switch(ctxt, ops, tss_selector, reason, rc = emulator_do_task_switch(ctxt, ops, tss_selector, reason,
has_error_code, error_code); has_error_code, error_code);
if (rc == X86EMUL_CONTINUE) { if (rc == X86EMUL_CONTINUE) {
memcpy(ctxt->vcpu->arch.regs, c->regs, sizeof c->regs);
rc = writeback(ctxt, ops); rc = writeback(ctxt, ops);
if (rc == X86EMUL_CONTINUE) if (rc == X86EMUL_CONTINUE)
ctxt->eip = c->eip; ctxt->eip = c->eip;
...@@ -2525,13 +2519,6 @@ x86_emulate_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops) ...@@ -2525,13 +2519,6 @@ x86_emulate_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
ctxt->interruptibility = 0; ctxt->interruptibility = 0;
ctxt->decode.mem_read.pos = 0; ctxt->decode.mem_read.pos = 0;
/* Shadow copy of register state. Committed on successful emulation.
* NOTE: we can copy them from vcpu as x86_decode_insn() doesn't
* modify them.
*/
memcpy(c->regs, ctxt->vcpu->arch.regs, sizeof c->regs);
if (ctxt->mode == X86EMUL_MODE_PROT64 && (c->d & No64)) { if (ctxt->mode == X86EMUL_MODE_PROT64 && (c->d & No64)) {
kvm_queue_exception(ctxt->vcpu, UD_VECTOR); kvm_queue_exception(ctxt->vcpu, UD_VECTOR);
goto done; goto done;
...@@ -3031,8 +3018,6 @@ x86_emulate_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops) ...@@ -3031,8 +3018,6 @@ x86_emulate_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
* without decoding * without decoding
*/ */
ctxt->decode.mem_read.end = 0; ctxt->decode.mem_read.end = 0;
/* Commit shadow register state. */
memcpy(ctxt->vcpu->arch.regs, c->regs, sizeof c->regs);
ctxt->eip = c->eip; ctxt->eip = c->eip;
done: done:
......
...@@ -3844,7 +3844,7 @@ int emulate_instruction(struct kvm_vcpu *vcpu, ...@@ -3844,7 +3844,7 @@ int emulate_instruction(struct kvm_vcpu *vcpu,
int emulation_type) int emulation_type)
{ {
int r, shadow_mask; int r, shadow_mask;
struct decode_cache *c; struct decode_cache *c = &vcpu->arch.emulate_ctxt.decode;
kvm_clear_exception_queue(vcpu); kvm_clear_exception_queue(vcpu);
vcpu->arch.mmio_fault_cr2 = cr2; vcpu->arch.mmio_fault_cr2 = cr2;
...@@ -3869,13 +3869,14 @@ int emulate_instruction(struct kvm_vcpu *vcpu, ...@@ -3869,13 +3869,14 @@ int emulate_instruction(struct kvm_vcpu *vcpu,
? X86EMUL_MODE_VM86 : cs_l ? X86EMUL_MODE_VM86 : cs_l
? X86EMUL_MODE_PROT64 : cs_db ? X86EMUL_MODE_PROT64 : cs_db
? X86EMUL_MODE_PROT32 : X86EMUL_MODE_PROT16; ? X86EMUL_MODE_PROT32 : X86EMUL_MODE_PROT16;
memset(c, 0, sizeof(struct decode_cache));
memcpy(c->regs, vcpu->arch.regs, sizeof c->regs);
r = x86_decode_insn(&vcpu->arch.emulate_ctxt, &emulate_ops); r = x86_decode_insn(&vcpu->arch.emulate_ctxt, &emulate_ops);
trace_kvm_emulate_insn_start(vcpu); trace_kvm_emulate_insn_start(vcpu);
/* Only allow emulation of specific instructions on #UD /* Only allow emulation of specific instructions on #UD
* (namely VMMCALL, sysenter, sysexit, syscall)*/ * (namely VMMCALL, sysenter, sysexit, syscall)*/
c = &vcpu->arch.emulate_ctxt.decode;
if (emulation_type & EMULTYPE_TRAP_UD) { if (emulation_type & EMULTYPE_TRAP_UD) {
if (!c->twobyte) if (!c->twobyte)
return EMULATE_FAIL; return EMULATE_FAIL;
...@@ -3916,6 +3917,10 @@ int emulate_instruction(struct kvm_vcpu *vcpu, ...@@ -3916,6 +3917,10 @@ int emulate_instruction(struct kvm_vcpu *vcpu,
return EMULATE_DONE; return EMULATE_DONE;
} }
/* this is needed for vmware backdor interface to work since it
changes registers values during IO operation */
memcpy(c->regs, vcpu->arch.regs, sizeof c->regs);
restart: restart:
r = x86_emulate_insn(&vcpu->arch.emulate_ctxt, &emulate_ops); r = x86_emulate_insn(&vcpu->arch.emulate_ctxt, &emulate_ops);
...@@ -3936,6 +3941,7 @@ int emulate_instruction(struct kvm_vcpu *vcpu, ...@@ -3936,6 +3941,7 @@ int emulate_instruction(struct kvm_vcpu *vcpu,
shadow_mask = vcpu->arch.emulate_ctxt.interruptibility; shadow_mask = vcpu->arch.emulate_ctxt.interruptibility;
kvm_x86_ops->set_interrupt_shadow(vcpu, shadow_mask); kvm_x86_ops->set_interrupt_shadow(vcpu, shadow_mask);
kvm_x86_ops->set_rflags(vcpu, vcpu->arch.emulate_ctxt.eflags); kvm_x86_ops->set_rflags(vcpu, vcpu->arch.emulate_ctxt.eflags);
memcpy(vcpu->arch.regs, c->regs, sizeof c->regs);
kvm_rip_write(vcpu, vcpu->arch.emulate_ctxt.eip); kvm_rip_write(vcpu, vcpu->arch.emulate_ctxt.eip);
if (vcpu->arch.pio.count) { if (vcpu->arch.pio.count) {
...@@ -4919,6 +4925,7 @@ int kvm_arch_vcpu_ioctl_set_mpstate(struct kvm_vcpu *vcpu, ...@@ -4919,6 +4925,7 @@ int kvm_arch_vcpu_ioctl_set_mpstate(struct kvm_vcpu *vcpu,
int kvm_task_switch(struct kvm_vcpu *vcpu, u16 tss_selector, int reason, int kvm_task_switch(struct kvm_vcpu *vcpu, u16 tss_selector, int reason,
bool has_error_code, u32 error_code) bool has_error_code, u32 error_code)
{ {
struct decode_cache *c = &vcpu->arch.emulate_ctxt.decode;
int cs_db, cs_l, ret; int cs_db, cs_l, ret;
cache_all_regs(vcpu); cache_all_regs(vcpu);
...@@ -4933,6 +4940,8 @@ int kvm_task_switch(struct kvm_vcpu *vcpu, u16 tss_selector, int reason, ...@@ -4933,6 +4940,8 @@ int kvm_task_switch(struct kvm_vcpu *vcpu, u16 tss_selector, int reason,
? X86EMUL_MODE_VM86 : cs_l ? X86EMUL_MODE_VM86 : cs_l
? X86EMUL_MODE_PROT64 : cs_db ? X86EMUL_MODE_PROT64 : cs_db
? X86EMUL_MODE_PROT32 : X86EMUL_MODE_PROT16; ? X86EMUL_MODE_PROT32 : X86EMUL_MODE_PROT16;
memset(c, 0, sizeof(struct decode_cache));
memcpy(c->regs, vcpu->arch.regs, sizeof c->regs);
ret = emulator_task_switch(&vcpu->arch.emulate_ctxt, &emulate_ops, ret = emulator_task_switch(&vcpu->arch.emulate_ctxt, &emulate_ops,
tss_selector, reason, has_error_code, tss_selector, reason, has_error_code,
...@@ -4941,6 +4950,7 @@ int kvm_task_switch(struct kvm_vcpu *vcpu, u16 tss_selector, int reason, ...@@ -4941,6 +4950,7 @@ int kvm_task_switch(struct kvm_vcpu *vcpu, u16 tss_selector, int reason,
if (ret) if (ret)
return EMULATE_FAIL; return EMULATE_FAIL;
memcpy(vcpu->arch.regs, c->regs, sizeof c->regs);
kvm_rip_write(vcpu, vcpu->arch.emulate_ctxt.eip); kvm_rip_write(vcpu, vcpu->arch.emulate_ctxt.eip);
kvm_x86_ops->set_rflags(vcpu, vcpu->arch.emulate_ctxt.eflags); kvm_x86_ops->set_rflags(vcpu, vcpu->arch.emulate_ctxt.eflags);
return EMULATE_DONE; return EMULATE_DONE;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment