KVM: x86: emulation of dword cmov on long-mode should clear [63:32]
authorNadav Amit <namit@cs.technion.ac.il>
Sun, 15 Jun 2014 13:13:00 +0000 (16:13 +0300)
committerPaolo Bonzini <pbonzini@redhat.com>
Thu, 19 Jun 2014 10:52:10 +0000 (12:52 +0200)
Even if the condition of cmov is not satisfied, bits[63:32] should be cleared.
This is clearly stated in Intel's CMOVcc documentation.  The solution is to
reassign the destination onto itself if the condition is unsatisfied.  For that
matter the original destination value needs to be read.

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

index 27ce386..6f09b2e 100644 (file)
@@ -3923,7 +3923,7 @@ static const struct opcode twobyte_table[256] = {
        N, N,
        N, N, N, N, N, N, N, N,
        /* 0x40 - 0x4F */
-       X16(D(DstReg | SrcMem | ModRM | Mov)),
+       X16(D(DstReg | SrcMem | ModRM)),
        /* 0x50 - 0x5F */
        N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N,
        /* 0x60 - 0x6F */
@@ -4824,8 +4824,10 @@ twobyte_insn:
                ops->get_dr(ctxt, ctxt->modrm_reg, &ctxt->dst.val);
                break;
        case 0x40 ... 0x4f:     /* cmov */
-               ctxt->dst.val = ctxt->dst.orig_val = ctxt->src.val;
-               if (!test_cc(ctxt->b, ctxt->eflags))
+               if (test_cc(ctxt->b, ctxt->eflags))
+                       ctxt->dst.val = ctxt->src.val;
+               else if (ctxt->mode != X86EMUL_MODE_PROT64 ||
+                        ctxt->op_bytes != 4)
                        ctxt->dst.type = OP_NONE; /* no writeback */
                break;
        case 0x80 ... 0x8f: /* jnz rel, etc*/