KVM: x86: Emulator does not decode clflush well
authorNadav Amit <namit@cs.technion.ac.il>
Mon, 13 Oct 2014 10:04:13 +0000 (13:04 +0300)
committerPaolo Bonzini <pbonzini@redhat.com>
Fri, 24 Oct 2014 11:30:36 +0000 (13:30 +0200)
Currently, all group15 instructions are decoded as clflush (e.g., mfence,
xsave).  In addition, the clflush instruction requires no prefix (66/f2/f3)
would exist. If prefix exists it may encode a different instruction (e.g.,
clflushopt).

Creating a group for clflush, and different group for each prefix.

This has been the case forever, but the next patch needs the cflush group
in order to fix a bug introduced in 3.17.

Fixes: 41061cdb98a0bec464278b4db8e894a3121671f5
Cc: stable@vger.kernel.org
Signed-off-by: Nadav Amit <namit@cs.technion.ac.il>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
arch/x86/kvm/emulate.c

index eb3b1c46f995d17b242ff5d80d2cdc6d87336d0d..97da5034d81262e41d74f8d7785f0a084c60b13d 100644 (file)
@@ -3462,6 +3462,12 @@ static int em_bswap(struct x86_emulate_ctxt *ctxt)
        return X86EMUL_CONTINUE;
 }
 
+static int em_clflush(struct x86_emulate_ctxt *ctxt)
+{
+       /* emulating clflush regardless of cpuid */
+       return X86EMUL_CONTINUE;
+}
+
 static bool valid_cr(int nr)
 {
        switch (nr) {
@@ -3800,6 +3806,16 @@ static const struct opcode group11[] = {
        X7(D(Undefined)),
 };
 
+static const struct gprefix pfx_0f_ae_7 = {
+       I(0, em_clflush), N, N, N,
+};
+
+static const struct group_dual group15 = { {
+       N, N, N, N, N, N, N, GP(0, &pfx_0f_ae_7),
+}, {
+       N, N, N, N, N, N, N, N,
+} };
+
 static const struct gprefix pfx_0f_6f_0f_7f = {
        I(Mmx, em_mov), I(Sse | Aligned, em_mov), N, I(Sse | Unaligned, em_mov),
 };
@@ -4063,7 +4079,7 @@ static const struct opcode twobyte_table[256] = {
        F(DstMem | SrcReg | ModRM | BitOp | Lock | PageTable, em_bts),
        F(DstMem | SrcReg | Src2ImmByte | ModRM, em_shrd),
        F(DstMem | SrcReg | Src2CL | ModRM, em_shrd),
-       D(ModRM), F(DstReg | SrcMem | ModRM, em_imul),
+       GD(0, &group15), F(DstReg | SrcMem | ModRM, em_imul),
        /* 0xB0 - 0xB7 */
        I2bv(DstMem | SrcReg | ModRM | Lock | PageTable, em_cmpxchg),
        I(DstReg | SrcMemFAddr | ModRM | Src2SS, em_lseg),
@@ -4993,8 +5009,6 @@ twobyte_insn:
        case 0x90 ... 0x9f:     /* setcc r/m8 */
                ctxt->dst.val = test_cc(ctxt->b, ctxt->eflags);
                break;
-       case 0xae:              /* clflush */
-               break;
        case 0xb6 ... 0xb7:     /* movzx */
                ctxt->dst.bytes = ctxt->op_bytes;
                ctxt->dst.val = (ctxt->src.bytes == 1) ? (u8) ctxt->src.val