summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNadav Amit <namit@cs.technion.ac.il>2014-06-15 15:12:58 +0200
committerPaolo Bonzini <pbonzini@redhat.com>2014-06-19 12:52:09 +0200
commitee212297cd425620867d4398d55d068c4203768c (patch)
tree693f75789abbef0339db3cf7a114b963cadae5a0
parentKVM: x86: bit-ops emulation ignores offset on 64-bit (diff)
downloadlinux-ee212297cd425620867d4398d55d068c4203768c.tar.xz
linux-ee212297cd425620867d4398d55d068c4203768c.zip
KVM: x86: Wrong emulation on 'xadd X, X'
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>
-rw-r--r--arch/x86/kvm/emulate.c10
1 files changed, 5 insertions, 5 deletions
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
index 439a3286406a..0d5ecbd45882 100644
--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -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