--- a/xen/arch/x86/x86_emulate/x86_emulate.c
+++ b/xen/arch/x86/x86_emulate/x86_emulate.c
@@ -182,7 +182,7 @@ static const opcode_desc_t opcode_table[
 
 static const opcode_desc_t twobyte_table[256] = {
     /* 0x00 - 0x07 */
-    SrcMem16|ModRM, ImplicitOps|ModRM, ModRM, ModRM,
+    ModRM, ImplicitOps|ModRM, ModRM, ModRM,
     0, ImplicitOps, ImplicitOps, ImplicitOps,
     /* 0x08 - 0x0F */
     ImplicitOps, ImplicitOps, 0, ImplicitOps,
@@ -419,6 +419,7 @@ typedef union {
 /* Control register flags. */
 #define CR0_PE    (1<<0)
 #define CR4_TSD   (1<<2)
+#define CR4_UMIP  (1<<11)
 
 /* EFLAGS bit definitions. */
 #define EFLG_VIP  (1<<20)
@@ -1493,6 +1494,17 @@ static bool is_aligned(enum x86_segment
     return !((reg.base + offs) & (size - 1));
 }
 
+static bool umip_active(struct x86_emulate_ctxt *ctxt,
+                        const struct x86_emulate_ops *ops)
+{
+    unsigned long cr4;
+
+    /* Intentionally not using mode_ring0() here to avoid its fail_if(). */
+    return get_cpl(ctxt, ops) > 0 &&
+           ops->read_cr && ops->read_cr(4, &cr4, ctxt) == X86EMUL_OKAY &&
+           (cr4 & CR4_UMIP);
+}
+
 /* Inject a software interrupt/exception, emulating if needed. */
 static int inject_swint(enum x86_swint_type type,
                         uint8_t vector, uint8_t insn_len,
@@ -2068,10 +2080,20 @@ x86_decode(
             break;
 
         case ext_0f:
-        case ext_0f3a:
-        case ext_8f08:
-        case ext_8f09:
-        case ext_8f0a:
+            switch ( b )
+            {
+            case 0x00: /* Grp6 */
+                switch ( modrm_reg & 6 )
+                {
+                case 0:
+                    d |= DstMem | SrcImplicit | Mov;
+                    break;
+                case 2: case 4:
+                    d |= SrcMem16;
+                    break;
+                }
+                break;
+            }
             break;
 
         case ext_0f38:
@@ -2087,6 +2109,12 @@ x86_decode(
             }
             break;
 
+        case ext_0f3a:
+        case ext_8f08:
+        case ext_8f09:
+        case ext_8f0a:
+            break;
+
         default:
             ASSERT_UNREACHABLE();
         }
@@ -4179,13 +4207,34 @@ x86_emulate(
         break;
 
     case X86EMUL_OPC(0x0f, 0x00): /* Grp6 */
-        fail_if((modrm_reg & 6) != 2);
+    {
+        enum x86_segment seg = (modrm_reg & 1) ? x86_seg_tr : x86_seg_ldtr;
+
         generate_exception_if(!in_protmode(ctxt, ops), EXC_UD, -1);
-        generate_exception_if(!mode_ring0(), EXC_GP, 0);
-        if ( (rc = load_seg((modrm_reg & 1) ? x86_seg_tr : x86_seg_ldtr,
-                            src.val, 0, NULL, ctxt, ops)) != 0 )
-            goto done;
+        switch ( modrm_reg & 6 )
+        {
+            struct segment_register sreg;
+
+        case 0: /* sldt / str */
+            generate_exception_if(umip_active(ctxt, ops), EXC_GP, 0);
+            fail_if(!ops->read_segment);
+            if ( (rc = ops->read_segment(seg, &sreg, ctxt)) != 0 )
+                goto done;
+            dst.val = sreg.sel;
+            if ( dst.type == OP_MEM )
+                dst.bytes = 2;
+            break;
+        case 2: /* lldt / ltr */
+            generate_exception_if(!mode_ring0(), EXC_GP, 0);
+            if ( (rc = load_seg(seg, src.val, 0, NULL, ctxt, ops)) != 0 )
+                goto done;
+            break;
+        default:
+            generate_exception_if(true, EXC_UD, -1);
+            break;
+        }
         break;
+    }
 
     case X86EMUL_OPC(0x0f, 0x01): /* Grp7 */ {
         struct segment_register reg;
@@ -4282,6 +4331,7 @@ x86_emulate(
         case 0: /* sgdt */
         case 1: /* sidt */
             generate_exception_if(ea.type != OP_MEM, EXC_UD, -1);
+            generate_exception_if(umip_active(ctxt, ops), EXC_GP, 0);
             fail_if(ops->read_segment == NULL);
             if ( (rc = ops->read_segment((modrm_reg & 1) ?
                                          x86_seg_idtr : x86_seg_gdtr,
@@ -4316,6 +4366,7 @@ x86_emulate(
                 goto done;
             break;
         case 4: /* smsw */
+            generate_exception_if(umip_active(ctxt, ops), EXC_GP, 0);
             ea.bytes = (ea.type == OP_MEM) ? 2 : op_bytes;
             dst = ea;
             fail_if(ops->read_cr == NULL);
