diff options
author | Gleb Natapov <gleb@redhat.com> | 2010-04-28 12:15:42 -0400 |
---|---|---|
committer | Avi Kivity <avi@redhat.com> | 2010-08-01 03:35:36 -0400 |
commit | 4d2179e1e9cb74b25a8181a506600d96e15504fb (patch) | |
tree | 142bb9f234bf52d5b021cb6248049e7ee2d12cff | |
parent | bdb475a323858101f4a5ad6a1a04b1dd8885325a (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.c | 15 | ||||
-rw-r--r-- | arch/x86/kvm/x86.c | 14 |
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 | ||
3038 | done: | 3023 | done: |
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 | |||
3919 | restart: | 3924 | restart: |
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, | |||
4919 | int kvm_task_switch(struct kvm_vcpu *vcpu, u16 tss_selector, int reason, | 4925 | int 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; |