diff options
author | Avi Kivity <avi@redhat.com> | 2010-08-17 04:22:17 -0400 |
---|---|---|
committer | Avi Kivity <avi@redhat.com> | 2010-10-24 04:51:10 -0400 |
commit | 0fa6ccbd281221bc7d46aff82d846e1f4c1985df (patch) | |
tree | fcb27435dbeb9ee5e0c10b39a30f4aed4a4230e2 | |
parent | f6b33fc5046642b669c3197bf08639172e4cffad (diff) |
KVM: x86 emulator: fix REPZ/REPNZ termination condition
EFLAGS.ZF needs to be checked after each iteration, not before.
Signed-off-by: Avi Kivity <avi@redhat.com>
-rw-r--r-- | arch/x86/kvm/emulate.c | 41 |
1 files changed, 20 insertions, 21 deletions
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c index 09c9210db75d..aab62d50752e 100644 --- a/arch/x86/kvm/emulate.c +++ b/arch/x86/kvm/emulate.c | |||
@@ -2781,28 +2781,10 @@ x86_emulate_insn(struct x86_emulate_ctxt *ctxt) | |||
2781 | ctxt->restart = true; | 2781 | ctxt->restart = true; |
2782 | /* All REP prefixes have the same first termination condition */ | 2782 | /* All REP prefixes have the same first termination condition */ |
2783 | if (address_mask(c, c->regs[VCPU_REGS_RCX]) == 0) { | 2783 | if (address_mask(c, c->regs[VCPU_REGS_RCX]) == 0) { |
2784 | string_done: | ||
2785 | ctxt->restart = false; | 2784 | ctxt->restart = false; |
2786 | ctxt->eip = c->eip; | 2785 | ctxt->eip = c->eip; |
2787 | goto done; | 2786 | goto done; |
2788 | } | 2787 | } |
2789 | /* The second termination condition only applies for REPE | ||
2790 | * and REPNE. Test if the repeat string operation prefix is | ||
2791 | * REPE/REPZ or REPNE/REPNZ and if it's the case it tests the | ||
2792 | * corresponding termination condition according to: | ||
2793 | * - if REPE/REPZ and ZF = 0 then done | ||
2794 | * - if REPNE/REPNZ and ZF = 1 then done | ||
2795 | */ | ||
2796 | if ((c->b == 0xa6) || (c->b == 0xa7) || | ||
2797 | (c->b == 0xae) || (c->b == 0xaf)) { | ||
2798 | if ((c->rep_prefix == REPE_PREFIX) && | ||
2799 | ((ctxt->eflags & EFLG_ZF) == 0)) | ||
2800 | goto string_done; | ||
2801 | if ((c->rep_prefix == REPNE_PREFIX) && | ||
2802 | ((ctxt->eflags & EFLG_ZF) == EFLG_ZF)) | ||
2803 | goto string_done; | ||
2804 | } | ||
2805 | c->eip = ctxt->eip; | ||
2806 | } | 2788 | } |
2807 | 2789 | ||
2808 | if ((c->src.type == OP_MEM) && !(c->d & NoAccess)) { | 2790 | if ((c->src.type == OP_MEM) && !(c->d & NoAccess)) { |
@@ -3229,20 +3211,37 @@ writeback: | |||
3229 | if (c->rep_prefix && (c->d & String)) { | 3211 | if (c->rep_prefix && (c->d & String)) { |
3230 | struct read_cache *rc = &ctxt->decode.io_read; | 3212 | struct read_cache *rc = &ctxt->decode.io_read; |
3231 | register_address_increment(c, &c->regs[VCPU_REGS_RCX], -1); | 3213 | register_address_increment(c, &c->regs[VCPU_REGS_RCX], -1); |
3214 | /* The second termination condition only applies for REPE | ||
3215 | * and REPNE. Test if the repeat string operation prefix is | ||
3216 | * REPE/REPZ or REPNE/REPNZ and if it's the case it tests the | ||
3217 | * corresponding termination condition according to: | ||
3218 | * - if REPE/REPZ and ZF = 0 then done | ||
3219 | * - if REPNE/REPNZ and ZF = 1 then done | ||
3220 | */ | ||
3221 | if (((c->b == 0xa6) || (c->b == 0xa7) || | ||
3222 | (c->b == 0xae) || (c->b == 0xaf)) | ||
3223 | && (((c->rep_prefix == REPE_PREFIX) && | ||
3224 | ((ctxt->eflags & EFLG_ZF) == 0)) | ||
3225 | || ((c->rep_prefix == REPNE_PREFIX) && | ||
3226 | ((ctxt->eflags & EFLG_ZF) == EFLG_ZF)))) | ||
3227 | ctxt->restart = false; | ||
3232 | /* | 3228 | /* |
3233 | * Re-enter guest when pio read ahead buffer is empty or, | 3229 | * Re-enter guest when pio read ahead buffer is empty or, |
3234 | * if it is not used, after each 1024 iteration. | 3230 | * if it is not used, after each 1024 iteration. |
3235 | */ | 3231 | */ |
3236 | if ((rc->end == 0 && !(c->regs[VCPU_REGS_RCX] & 0x3ff)) || | 3232 | else if ((rc->end == 0 && !(c->regs[VCPU_REGS_RCX] & 0x3ff)) || |
3237 | (rc->end != 0 && rc->end == rc->pos)) | 3233 | (rc->end != 0 && rc->end == rc->pos)) { |
3238 | ctxt->restart = false; | 3234 | ctxt->restart = false; |
3235 | c->eip = ctxt->eip; | ||
3236 | } | ||
3239 | } | 3237 | } |
3240 | /* | 3238 | /* |
3241 | * reset read cache here in case string instruction is restared | 3239 | * reset read cache here in case string instruction is restared |
3242 | * without decoding | 3240 | * without decoding |
3243 | */ | 3241 | */ |
3244 | ctxt->decode.mem_read.end = 0; | 3242 | ctxt->decode.mem_read.end = 0; |
3245 | ctxt->eip = c->eip; | 3243 | if (!ctxt->restart) |
3244 | ctxt->eip = c->eip; | ||
3246 | 3245 | ||
3247 | done: | 3246 | done: |
3248 | return (rc == X86EMUL_UNHANDLEABLE) ? -1 : 0; | 3247 | return (rc == X86EMUL_UNHANDLEABLE) ? -1 : 0; |