KVM: x86: Wrong emulation on 'xadd X, X'
authorNadav Amit <namit@cs.technion.ac.il>
Sun, 15 Jun 2014 13:12:58 +0000 (16:12 +0300)
committerPaolo Bonzini <pbonzini@redhat.com>
Thu, 19 Jun 2014 10:52:09 +0000 (12:52 +0200)
The emulator does not emulate the xadd instruction correctly if the two
operands are the same.  In this (unlikely) situation the result should be the
sum of X and X (2X) when it is currently X.  The solution is to first perform
writeback to the source, before writing to the destination.  The only
instruction which should be affected is xadd, as the other instructions that
perform writeback to the source use the extended accumlator (e.g., RAX:RDX).

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

index 439a3286406a4c641419372412bbd89e60d2284c..0d5ecbd458824f2e7d4c38362e12a913745dcb91 100644 (file)
@@ -4736,17 +4736,17 @@ special_insn:
                goto done;
 
 writeback:
-       if (!(ctxt->d & NoWrite)) {
-               rc = writeback(ctxt, &ctxt->dst);
-               if (rc != X86EMUL_CONTINUE)
-                       goto done;
-       }
        if (ctxt->d & SrcWrite) {
                BUG_ON(ctxt->src.type == OP_MEM || ctxt->src.type == OP_MEM_STR);
                rc = writeback(ctxt, &ctxt->src);
                if (rc != X86EMUL_CONTINUE)
                        goto done;
        }
+       if (!(ctxt->d & NoWrite)) {
+               rc = writeback(ctxt, &ctxt->dst);
+               if (rc != X86EMUL_CONTINUE)
+                       goto done;
+       }
 
        /*
         * restore dst type in case the decoding will be reused