aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGleb Natapov <gleb@redhat.com>2010-04-28 12:15:42 -0400
committerAvi Kivity <avi@redhat.com>2010-08-01 03:35:36 -0400
commit4d2179e1e9cb74b25a8181a506600d96e15504fb (patch)
tree142bb9f234bf52d5b021cb6248049e7ee2d12cff
parentbdb475a323858101f4a5ad6a1a04b1dd8885325a (diff)
KVM: x86 emulator: handle shadowed registers outside emulator
Emulator shouldn't access vcpu directly. Signed-off-by: Gleb Natapov <gleb@redhat.com> Signed-off-by: Avi Kivity <avi@redhat.com>
-rw-r--r--arch/x86/kvm/emulate.c15
-rw-r--r--arch/x86/kvm/x86.c14
2 files changed, 12 insertions, 17 deletions
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
index 42cb7d71ff55..97a42e8c00d0 100644
--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -941,12 +941,9 @@ x86_decode_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
941 /* we cannot decode insn before we complete previous rep insn */ 941 /* we cannot decode insn before we complete previous rep insn */
942 WARN_ON(ctxt->restart); 942 WARN_ON(ctxt->restart);
943 943
944 /* Shadow copy of register state. Committed on successful emulation. */
945 memset(c, 0, sizeof(struct decode_cache));
946 c->eip = ctxt->eip; 944 c->eip = ctxt->eip;
947 c->fetch.start = c->fetch.end = c->eip; 945 c->fetch.start = c->fetch.end = c->eip;
948 ctxt->cs_base = seg_base(ctxt, ops, VCPU_SREG_CS); 946 ctxt->cs_base = seg_base(ctxt, ops, VCPU_SREG_CS);
949 memcpy(c->regs, ctxt->vcpu->arch.regs, sizeof c->regs);
950 947
951 switch (mode) { 948 switch (mode) {
952 case X86EMUL_MODE_REAL: 949 case X86EMUL_MODE_REAL:
@@ -2486,16 +2483,13 @@ int emulator_task_switch(struct x86_emulate_ctxt *ctxt,
2486 struct decode_cache *c = &ctxt->decode; 2483 struct decode_cache *c = &ctxt->decode;
2487 int rc; 2484 int rc;
2488 2485
2489 memset(c, 0, sizeof(struct decode_cache));
2490 c->eip = ctxt->eip; 2486 c->eip = ctxt->eip;
2491 memcpy(c->regs, ctxt->vcpu->arch.regs, sizeof c->regs);
2492 c->dst.type = OP_NONE; 2487 c->dst.type = OP_NONE;
2493 2488
2494 rc = emulator_do_task_switch(ctxt, ops, tss_selector, reason, 2489 rc = emulator_do_task_switch(ctxt, ops, tss_selector, reason,
2495 has_error_code, error_code); 2490 has_error_code, error_code);
2496 2491
2497 if (rc == X86EMUL_CONTINUE) { 2492 if (rc == X86EMUL_CONTINUE) {
2498 memcpy(ctxt->vcpu->arch.regs, c->regs, sizeof c->regs);
2499 rc = writeback(ctxt, ops); 2493 rc = writeback(ctxt, ops);
2500 if (rc == X86EMUL_CONTINUE) 2494 if (rc == X86EMUL_CONTINUE)
2501 ctxt->eip = c->eip; 2495 ctxt->eip = c->eip;
@@ -2525,13 +2519,6 @@ x86_emulate_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
2525 ctxt->interruptibility = 0; 2519 ctxt->interruptibility = 0;
2526 ctxt->decode.mem_read.pos = 0; 2520 ctxt->decode.mem_read.pos = 0;
2527 2521
2528 /* Shadow copy of register state. Committed on successful emulation.
2529 * NOTE: we can copy them from vcpu as x86_decode_insn() doesn't
2530 * modify them.
2531 */
2532
2533 memcpy(c->regs, ctxt->vcpu->arch.regs, sizeof c->regs);
2534
2535 if (ctxt->mode == X86EMUL_MODE_PROT64 && (c->d & No64)) { 2522 if (ctxt->mode == X86EMUL_MODE_PROT64 && (c->d & No64)) {
2536 kvm_queue_exception(ctxt->vcpu, UD_VECTOR); 2523 kvm_queue_exception(ctxt->vcpu, UD_VECTOR);
2537 goto done; 2524 goto done;
@@ -3031,8 +3018,6 @@ writeback:
3031 * without decoding 3018 * without decoding
3032 */ 3019 */
3033 ctxt->decode.mem_read.end = 0; 3020 ctxt->decode.mem_read.end = 0;
3034 /* Commit shadow register state. */
3035 memcpy(ctxt->vcpu->arch.regs, c->regs, sizeof c->regs);
3036 ctxt->eip = c->eip; 3021 ctxt->eip = c->eip;
3037 3022
3038done: 3023done:
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 04ca343ee512..21d36081a9d9 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -3844,7 +3844,7 @@ int emulate_instruction(struct kvm_vcpu *vcpu,
3844 int emulation_type) 3844 int emulation_type)
3845{ 3845{
3846 int r, shadow_mask; 3846 int r, shadow_mask;
3847 struct decode_cache *c; 3847 struct decode_cache *c = &vcpu->arch.emulate_ctxt.decode;
3848 3848
3849 kvm_clear_exception_queue(vcpu); 3849 kvm_clear_exception_queue(vcpu);
3850 vcpu->arch.mmio_fault_cr2 = cr2; 3850 vcpu->arch.mmio_fault_cr2 = cr2;
@@ -3869,13 +3869,14 @@ int emulate_instruction(struct kvm_vcpu *vcpu,
3869 ? X86EMUL_MODE_VM86 : cs_l 3869 ? X86EMUL_MODE_VM86 : cs_l
3870 ? X86EMUL_MODE_PROT64 : cs_db 3870 ? X86EMUL_MODE_PROT64 : cs_db
3871 ? X86EMUL_MODE_PROT32 : X86EMUL_MODE_PROT16; 3871 ? X86EMUL_MODE_PROT32 : X86EMUL_MODE_PROT16;
3872 memset(c, 0, sizeof(struct decode_cache));
3873 memcpy(c->regs, vcpu->arch.regs, sizeof c->regs);
3872 3874
3873 r = x86_decode_insn(&vcpu->arch.emulate_ctxt, &emulate_ops); 3875 r = x86_decode_insn(&vcpu->arch.emulate_ctxt, &emulate_ops);
3874 trace_kvm_emulate_insn_start(vcpu); 3876 trace_kvm_emulate_insn_start(vcpu);
3875 3877
3876 /* Only allow emulation of specific instructions on #UD 3878 /* Only allow emulation of specific instructions on #UD
3877 * (namely VMMCALL, sysenter, sysexit, syscall)*/ 3879 * (namely VMMCALL, sysenter, sysexit, syscall)*/
3878 c = &vcpu->arch.emulate_ctxt.decode;
3879 if (emulation_type & EMULTYPE_TRAP_UD) { 3880 if (emulation_type & EMULTYPE_TRAP_UD) {
3880 if (!c->twobyte) 3881 if (!c->twobyte)
3881 return EMULATE_FAIL; 3882 return EMULATE_FAIL;
@@ -3916,6 +3917,10 @@ int emulate_instruction(struct kvm_vcpu *vcpu,
3916 return EMULATE_DONE; 3917 return EMULATE_DONE;
3917 } 3918 }
3918 3919
3920 /* this is needed for vmware backdor interface to work since it
3921 changes registers values during IO operation */
3922 memcpy(c->regs, vcpu->arch.regs, sizeof c->regs);
3923
3919restart: 3924restart:
3920 r = x86_emulate_insn(&vcpu->arch.emulate_ctxt, &emulate_ops); 3925 r = x86_emulate_insn(&vcpu->arch.emulate_ctxt, &emulate_ops);
3921 3926
@@ -3936,6 +3941,7 @@ restart:
3936 shadow_mask = vcpu->arch.emulate_ctxt.interruptibility; 3941 shadow_mask = vcpu->arch.emulate_ctxt.interruptibility;
3937 kvm_x86_ops->set_interrupt_shadow(vcpu, shadow_mask); 3942 kvm_x86_ops->set_interrupt_shadow(vcpu, shadow_mask);
3938 kvm_x86_ops->set_rflags(vcpu, vcpu->arch.emulate_ctxt.eflags); 3943 kvm_x86_ops->set_rflags(vcpu, vcpu->arch.emulate_ctxt.eflags);
3944 memcpy(vcpu->arch.regs, c->regs, sizeof c->regs);
3939 kvm_rip_write(vcpu, vcpu->arch.emulate_ctxt.eip); 3945 kvm_rip_write(vcpu, vcpu->arch.emulate_ctxt.eip);
3940 3946
3941 if (vcpu->arch.pio.count) { 3947 if (vcpu->arch.pio.count) {
@@ -4919,6 +4925,7 @@ int kvm_arch_vcpu_ioctl_set_mpstate(struct kvm_vcpu *vcpu,
4919int kvm_task_switch(struct kvm_vcpu *vcpu, u16 tss_selector, int reason, 4925int kvm_task_switch(struct kvm_vcpu *vcpu, u16 tss_selector, int reason,
4920 bool has_error_code, u32 error_code) 4926 bool has_error_code, u32 error_code)
4921{ 4927{
4928 struct decode_cache *c = &vcpu->arch.emulate_ctxt.decode;
4922 int cs_db, cs_l, ret; 4929 int cs_db, cs_l, ret;
4923 cache_all_regs(vcpu); 4930 cache_all_regs(vcpu);
4924 4931
@@ -4933,6 +4940,8 @@ int kvm_task_switch(struct kvm_vcpu *vcpu, u16 tss_selector, int reason,
4933 ? X86EMUL_MODE_VM86 : cs_l 4940 ? X86EMUL_MODE_VM86 : cs_l
4934 ? X86EMUL_MODE_PROT64 : cs_db 4941 ? X86EMUL_MODE_PROT64 : cs_db
4935 ? X86EMUL_MODE_PROT32 : X86EMUL_MODE_PROT16; 4942 ? X86EMUL_MODE_PROT32 : X86EMUL_MODE_PROT16;
4943 memset(c, 0, sizeof(struct decode_cache));
4944 memcpy(c->regs, vcpu->arch.regs, sizeof c->regs);
4936 4945
4937 ret = emulator_task_switch(&vcpu->arch.emulate_ctxt, &emulate_ops, 4946 ret = emulator_task_switch(&vcpu->arch.emulate_ctxt, &emulate_ops,
4938 tss_selector, reason, has_error_code, 4947 tss_selector, reason, has_error_code,
@@ -4941,6 +4950,7 @@ int kvm_task_switch(struct kvm_vcpu *vcpu, u16 tss_selector, int reason,
4941 if (ret) 4950 if (ret)
4942 return EMULATE_FAIL; 4951 return EMULATE_FAIL;
4943 4952
4953 memcpy(vcpu->arch.regs, c->regs, sizeof c->regs);
4944 kvm_rip_write(vcpu, vcpu->arch.emulate_ctxt.eip); 4954 kvm_rip_write(vcpu, vcpu->arch.emulate_ctxt.eip);
4945 kvm_x86_ops->set_rflags(vcpu, vcpu->arch.emulate_ctxt.eflags); 4955 kvm_x86_ops->set_rflags(vcpu, vcpu->arch.emulate_ctxt.eflags);
4946 return EMULATE_DONE; 4956 return EMULATE_DONE;