KVM: x86: emulating descriptor load misses long-mode case
[sfrench/cifs-2.6.git] / arch / x86 / kvm / emulate.c
index e5bf13003cd215def5ae6973480878b1352c09f3..a46207a0583508ad662d179f2db1ede320a7645e 100644 (file)
@@ -1504,6 +1504,15 @@ static int __load_segment_descriptor(struct x86_emulate_ctxt *ctxt,
                        if (rpl > cpl || dpl != cpl)
                                goto exception;
                }
+               /* in long-mode d/b must be clear if l is set */
+               if (seg_desc.d && seg_desc.l) {
+                       u64 efer = 0;
+
+                       ctxt->ops->get_msr(ctxt, MSR_EFER, &efer);
+                       if (efer & EFER_LMA)
+                               goto exception;
+               }
+
                /* CS(RPL) <- CPL */
                selector = (selector & 0xfffc) | cpl;
                break;
@@ -3139,12 +3148,8 @@ static int em_clts(struct x86_emulate_ctxt *ctxt)
 
 static int em_vmcall(struct x86_emulate_ctxt *ctxt)
 {
-       int rc;
+       int rc = ctxt->ops->fix_hypercall(ctxt);
 
-       if (ctxt->modrm_mod != 3 || ctxt->modrm_rm != 1)
-               return X86EMUL_UNHANDLEABLE;
-
-       rc = ctxt->ops->fix_hypercall(ctxt);
        if (rc != X86EMUL_CONTINUE)
                return rc;
 
@@ -3562,6 +3567,12 @@ static int check_perm_out(struct x86_emulate_ctxt *ctxt)
                F2bv(((_f) | DstReg | SrcMem | ModRM) & ~Lock, _e),     \
                F2bv(((_f) & ~Lock) | DstAcc | SrcImm, _e)
 
+static const struct opcode group7_rm0[] = {
+       N,
+       I(SrcNone | Priv | EmulateOnUD, em_vmcall),
+       N, N, N, N, N, N,
+};
+
 static const struct opcode group7_rm1[] = {
        DI(SrcNone | Priv, monitor),
        DI(SrcNone | Priv, mwait),
@@ -3655,7 +3666,7 @@ static const struct group_dual group7 = { {
        II(SrcMem16 | Mov | Priv,               em_lmsw, lmsw),
        II(SrcMem | ByteOp | Priv | NoAccess,   em_invlpg, invlpg),
 }, {
-       I(SrcNone | Priv | EmulateOnUD, em_vmcall),
+       EXT(0, group7_rm0),
        EXT(0, group7_rm1),
        N, EXT(0, group7_rm3),
        II(SrcNone | DstMem | Mov,              em_smsw, smsw), N,
@@ -3686,14 +3697,18 @@ static const struct gprefix pfx_0f_6f_0f_7f = {
        I(Mmx, em_mov), I(Sse | Aligned, em_mov), N, I(Sse | Unaligned, em_mov),
 };
 
-static const struct gprefix pfx_vmovntpx = {
-       I(0, em_mov), N, N, N,
+static const struct gprefix pfx_0f_2b = {
+       I(0, em_mov), I(0, em_mov), N, N,
 };
 
 static const struct gprefix pfx_0f_28_0f_29 = {
        I(Aligned, em_mov), I(Aligned, em_mov), N, N,
 };
 
+static const struct gprefix pfx_0f_e7 = {
+       N, I(Sse, em_mov), N, N,
+};
+
 static const struct escape escape_d9 = { {
        N, N, N, N, N, N, N, I(DstMem, em_fnstcw),
 }, {
@@ -3900,7 +3915,7 @@ static const struct opcode twobyte_table[256] = {
        N, N, N, N,
        GP(ModRM | DstReg | SrcMem | Mov | Sse, &pfx_0f_28_0f_29),
        GP(ModRM | DstMem | SrcReg | Mov | Sse, &pfx_0f_28_0f_29),
-       N, GP(ModRM | DstMem | SrcReg | Sse | Mov | Aligned, &pfx_vmovntpx),
+       N, GP(ModRM | DstMem | SrcReg | Mov | Sse, &pfx_0f_2b),
        N, N, N, N,
        /* 0x30 - 0x3F */
        II(ImplicitOps | Priv, em_wrmsr, wrmsr),
@@ -3964,7 +3979,8 @@ static const struct opcode twobyte_table[256] = {
        /* 0xD0 - 0xDF */
        N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N,
        /* 0xE0 - 0xEF */
-       N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N,
+       N, N, N, N, N, N, N, GP(SrcReg | DstMem | ModRM | Mov, &pfx_0f_e7),
+       N, N, N, N, N, N, N, N,
        /* 0xF0 - 0xFF */
        N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N
 };