From: Mihai Donțu <mdontu@xxxxxxxxxxxxxxx> This is needed in order to be able to support guest code that uses movsd to write into pages that are marked for write tracking. Signed-off-by: Mihai Donțu <mdontu@xxxxxxxxxxxxxxx> Signed-off-by: Adalbert Lazăr <alazar@xxxxxxxxxxxxxxx> --- arch/x86/kvm/emulate.c | 32 +++++++++++++++++++++++++++----- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c index 34431cf31f74..9d38f892beea 100644 --- a/arch/x86/kvm/emulate.c +++ b/arch/x86/kvm/emulate.c @@ -1177,6 +1177,27 @@ static int em_fnstsw(struct x86_emulate_ctxt *ctxt) return X86EMUL_CONTINUE; } +static u8 simd_prefix_to_bytes(const struct x86_emulate_ctxt *ctxt, + int simd_prefix) +{ + u8 bytes; + + switch (ctxt->b) { + case 0x11: + /* movsd xmm, m64 */ + /* movups xmm, m128 */ + if (simd_prefix == 0xf2) { + bytes = 8; + break; + } + /* fallthrough */ + default: + bytes = 16; + break; + } + return bytes; +} + static void decode_register_operand(struct x86_emulate_ctxt *ctxt, struct operand *op) { @@ -1187,7 +1208,7 @@ static void decode_register_operand(struct x86_emulate_ctxt *ctxt, if (ctxt->d & Sse) { op->type = OP_XMM; - op->bytes = 16; + op->bytes = ctxt->op_bytes; op->addr.xmm = reg; read_sse_reg(ctxt, &op->vec_val, reg); return; @@ -1238,7 +1259,7 @@ static int decode_modrm(struct x86_emulate_ctxt *ctxt, ctxt->d & ByteOp); if (ctxt->d & Sse) { op->type = OP_XMM; - op->bytes = 16; + op->bytes = ctxt->op_bytes; op->addr.xmm = ctxt->modrm_rm; read_sse_reg(ctxt, &op->vec_val, ctxt->modrm_rm); return rc; @@ -4529,7 +4550,7 @@ static const struct gprefix pfx_0f_2b = { }; static const struct gprefix pfx_0f_10_0f_11 = { - I(Unaligned, em_mov), I(Unaligned, em_mov), N, N, + I(Unaligned, em_mov), I(Unaligned, em_mov), I(Unaligned, em_mov), N, }; static const struct gprefix pfx_0f_28_0f_29 = { @@ -5097,7 +5118,7 @@ int x86_decode_insn(struct x86_emulate_ctxt *ctxt, void *insn, int insn_len) { int rc = X86EMUL_CONTINUE; int mode = ctxt->mode; - int def_op_bytes, def_ad_bytes, goffset, simd_prefix; + int def_op_bytes, def_ad_bytes, goffset, simd_prefix = 0; bool op_prefix = false; bool has_seg_override = false; struct opcode opcode; @@ -5320,7 +5341,8 @@ int x86_decode_insn(struct x86_emulate_ctxt *ctxt, void *insn, int insn_len) ctxt->op_bytes = 4; if (ctxt->d & Sse) - ctxt->op_bytes = 16; + ctxt->op_bytes = simd_prefix_to_bytes(ctxt, + simd_prefix); else if (ctxt->d & Mmx) ctxt->op_bytes = 8; }