aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAvi Kivity <avi@redhat.com>2010-08-17 04:22:17 -0400
committerAvi Kivity <avi@redhat.com>2010-10-24 04:51:10 -0400
commit0fa6ccbd281221bc7d46aff82d846e1f4c1985df (patch)
treefcb27435dbeb9ee5e0c10b39a30f4aed4a4230e2
parentf6b33fc5046642b669c3197bf08639172e4cffad (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.c41
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
3247done: 3246done:
3248 return (rc == X86EMUL_UNHANDLEABLE) ? -1 : 0; 3247 return (rc == X86EMUL_UNHANDLEABLE) ? -1 : 0;