aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kvm/emulate.c
diff options
context:
space:
mode:
authorNadav Amit <namit@cs.technion.ac.il>2014-06-15 09:13:00 -0400
committerPaolo Bonzini <pbonzini@redhat.com>2014-06-19 06:52:10 -0400
commit140bad89fd25db1aab60f80ed7874e9a9bdbae3b (patch)
tree804730300e75d1574caacd63a89fee2c0896894e /arch/x86/kvm/emulate.c
parent9e8919ae793f4edfaa29694a70f71a515ae9942a (diff)
KVM: x86: emulation of dword cmov on long-mode should clear [63:32]
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>
Diffstat (limited to 'arch/x86/kvm/emulate.c')
-rw-r--r--arch/x86/kvm/emulate.c8
1 files changed, 5 insertions, 3 deletions
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
index 27ce38693f09..6f09b2e555ef 100644
--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -3923,7 +3923,7 @@ static const struct opcode twobyte_table[256] = {
3923 N, N, 3923 N, N,
3924 N, N, N, N, N, N, N, N, 3924 N, N, N, N, N, N, N, N,
3925 /* 0x40 - 0x4F */ 3925 /* 0x40 - 0x4F */
3926 X16(D(DstReg | SrcMem | ModRM | Mov)), 3926 X16(D(DstReg | SrcMem | ModRM)),
3927 /* 0x50 - 0x5F */ 3927 /* 0x50 - 0x5F */
3928 N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, 3928 N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N,
3929 /* 0x60 - 0x6F */ 3929 /* 0x60 - 0x6F */
@@ -4824,8 +4824,10 @@ twobyte_insn:
4824 ops->get_dr(ctxt, ctxt->modrm_reg, &ctxt->dst.val); 4824 ops->get_dr(ctxt, ctxt->modrm_reg, &ctxt->dst.val);
4825 break; 4825 break;
4826 case 0x40 ... 0x4f: /* cmov */ 4826 case 0x40 ... 0x4f: /* cmov */
4827 ctxt->dst.val = ctxt->dst.orig_val = ctxt->src.val; 4827 if (test_cc(ctxt->b, ctxt->eflags))
4828 if (!test_cc(ctxt->b, ctxt->eflags)) 4828 ctxt->dst.val = ctxt->src.val;
4829 else if (ctxt->mode != X86EMUL_MODE_PROT64 ||
4830 ctxt->op_bytes != 4)
4829 ctxt->dst.type = OP_NONE; /* no writeback */ 4831 ctxt->dst.type = OP_NONE; /* no writeback */
4830 break; 4832 break;
4831 case 0x80 ... 0x8f: /* jnz rel, etc*/ 4833 case 0x80 ... 0x8f: /* jnz rel, etc*/