summaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorNadav Amit2014-06-02 17:34:07 +0200
committerPaolo Bonzini2014-06-18 17:46:17 +0200
commit37c564f2854bf75969d0ac26e03f5cf2bb7d639f (patch)
tree1058d95e55d2917e9d89ade00c29ca2c1a4d2a98 /arch
parentKVM: x86: sgdt and sidt are not privilaged (diff)
downloadkernel-qcow2-linux-37c564f2854bf75969d0ac26e03f5cf2bb7d639f.tar.gz
kernel-qcow2-linux-37c564f2854bf75969d0ac26e03f5cf2bb7d639f.tar.xz
kernel-qcow2-linux-37c564f2854bf75969d0ac26e03f5cf2bb7d639f.zip
KVM: x86: cmpxchg emulation should compare in reverse order
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>
Diffstat (limited to 'arch')
-rw-r--r--arch/x86/kvm/emulate.c5
1 files changed, 4 insertions, 1 deletions
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
index a16bf225cab0..4cb0da660283 100644
--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -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;
}