diff options
author | Gleb Natapov <gleb@redhat.com> | 2010-03-18 09:20:22 -0400 |
---|---|---|
committer | Avi Kivity <avi@redhat.com> | 2010-05-17 05:16:23 -0400 |
commit | d9271123a46011af26da680baeb7fdf67b498abf (patch) | |
tree | a63c0e86cb1e2d0203b84f3d3ce677d436668ce1 /arch | |
parent | a682e35449abc83d260a8219015c7cb4b25ecced (diff) |
KVM: x86 emulator: during rep emulation decrement ECX only if emulation succeeded
Signed-off-by: Gleb Natapov <gleb@redhat.com>
Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/x86/kvm/emulate.c | 15 |
1 files changed, 8 insertions, 7 deletions
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c index 3b32270a20db..594574d8b9e9 100644 --- a/arch/x86/kvm/emulate.c +++ b/arch/x86/kvm/emulate.c | |||
@@ -2411,13 +2411,13 @@ int emulator_task_switch(struct x86_emulate_ctxt *ctxt, | |||
2411 | } | 2411 | } |
2412 | 2412 | ||
2413 | static void string_addr_inc(struct x86_emulate_ctxt *ctxt, unsigned long base, | 2413 | static void string_addr_inc(struct x86_emulate_ctxt *ctxt, unsigned long base, |
2414 | int reg, unsigned long **ptr) | 2414 | int reg, struct operand *op) |
2415 | { | 2415 | { |
2416 | struct decode_cache *c = &ctxt->decode; | 2416 | struct decode_cache *c = &ctxt->decode; |
2417 | int df = (ctxt->eflags & EFLG_DF) ? -1 : 1; | 2417 | int df = (ctxt->eflags & EFLG_DF) ? -1 : 1; |
2418 | 2418 | ||
2419 | register_address_increment(c, &c->regs[reg], df * c->src.bytes); | 2419 | register_address_increment(c, &c->regs[reg], df * op->bytes); |
2420 | *ptr = (unsigned long *)register_address(c, base, c->regs[reg]); | 2420 | op->ptr = (unsigned long *)register_address(c, base, c->regs[reg]); |
2421 | } | 2421 | } |
2422 | 2422 | ||
2423 | int | 2423 | int |
@@ -2483,7 +2483,6 @@ x86_emulate_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops) | |||
2483 | goto done; | 2483 | goto done; |
2484 | } | 2484 | } |
2485 | } | 2485 | } |
2486 | register_address_increment(c, &c->regs[VCPU_REGS_RCX], -1); | ||
2487 | c->eip = ctxt->eip; | 2486 | c->eip = ctxt->eip; |
2488 | } | 2487 | } |
2489 | 2488 | ||
@@ -2936,11 +2935,13 @@ writeback: | |||
2936 | 2935 | ||
2937 | if ((c->d & SrcMask) == SrcSI) | 2936 | if ((c->d & SrcMask) == SrcSI) |
2938 | string_addr_inc(ctxt, seg_override_base(ctxt, c), VCPU_REGS_RSI, | 2937 | string_addr_inc(ctxt, seg_override_base(ctxt, c), VCPU_REGS_RSI, |
2939 | &c->src.ptr); | 2938 | &c->src); |
2940 | 2939 | ||
2941 | if ((c->d & DstMask) == DstDI) | 2940 | if ((c->d & DstMask) == DstDI) |
2942 | string_addr_inc(ctxt, es_base(ctxt), VCPU_REGS_RDI, | 2941 | string_addr_inc(ctxt, es_base(ctxt), VCPU_REGS_RDI, &c->dst); |
2943 | &c->dst.ptr); | 2942 | |
2943 | if (c->rep_prefix && (c->d & String)) | ||
2944 | register_address_increment(c, &c->regs[VCPU_REGS_RCX], -1); | ||
2944 | 2945 | ||
2945 | /* Commit shadow register state. */ | 2946 | /* Commit shadow register state. */ |
2946 | memcpy(ctxt->vcpu->arch.regs, c->regs, sizeof c->regs); | 2947 | memcpy(ctxt->vcpu->arch.regs, c->regs, sizeof c->regs); |