KVM: x86: cmpxchg emulation should compare in reverse order
authorNadav Amit <namit@cs.technion.ac.il>
Mon, 2 Jun 2014 15:34:07 +0000 (18:34 +0300)
committerPaolo Bonzini <pbonzini@redhat.com>
Wed, 18 Jun 2014 15:46:17 +0000 (17:46 +0200)
The current implementation of cmpxchg does not update the flags correctly,
since the accumulator should be compared with the destination and not the other
way around. The current implementation does not update the flags correctly.

Signed-off-by: Nadav Amit <namit@cs.technion.ac.il>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
arch/x86/kvm/emulate.c

index a16bf225cab01441b810d5e1147379bd17abdc4d..4cb0da66028391a93ecb6fe508340f6220724291 100644 (file)
@@ -2052,8 +2052,10 @@ static int em_ret_far_imm(struct x86_emulate_ctxt *ctxt)
 static int em_cmpxchg(struct x86_emulate_ctxt *ctxt)
 {
        /* Save real source value, then compare EAX against destination. */
+       ctxt->dst.orig_val = ctxt->dst.val;
+       ctxt->dst.val = reg_read(ctxt, VCPU_REGS_RAX);
        ctxt->src.orig_val = ctxt->src.val;
-       ctxt->src.val = reg_read(ctxt, VCPU_REGS_RAX);
+       ctxt->src.val = ctxt->dst.orig_val;
        fastop(ctxt, em_cmp);
 
        if (ctxt->eflags & EFLG_ZF) {
@@ -2063,6 +2065,7 @@ static int em_cmpxchg(struct x86_emulate_ctxt *ctxt)
                /* Failure: write the value we saw to EAX. */
                ctxt->dst.type = OP_REG;
                ctxt->dst.addr.reg = reg_rmw(ctxt, VCPU_REGS_RAX);
+               ctxt->dst.val = ctxt->dst.orig_val;
        }
        return X86EMUL_CONTINUE;
 }