]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - arch/x86/kvm/emulate.c
KVM: x86: Return UNHANDLABLE on unsupported SYSENTER
[karo-tx-linux.git] / arch / x86 / kvm / emulate.c
index 04769897479951b7c2f7157f1a1792340d15f9a4..dab9b74c29de9fec4cd305739458ab1a6419c0d6 100644 (file)
 #define CheckPerm   ((u64)1 << 49)  /* Has valid check_perm field */
 #define NoBigReal   ((u64)1 << 50)  /* No big real mode */
 #define PrivUD      ((u64)1 << 51)  /* #UD instead of #GP on CPL > 0 */
+#define NearBranch  ((u64)1 << 52)  /* Near branches */
 
 #define DstXacc     (DstAccLo | SrcAccHi | SrcWrite)
 
@@ -379,6 +380,15 @@ static int fastop(struct x86_emulate_ctxt *ctxt, void (*fop)(struct fastop *));
        ON64(FOP2E(op##q, rax, cl)) \
        FOP_END
 
+/* 2 operand, src and dest are reversed */
+#define FASTOP2R(op, name) \
+       FOP_START(name) \
+       FOP2E(op##b, dl, al) \
+       FOP2E(op##w, dx, ax) \
+       FOP2E(op##l, edx, eax) \
+       ON64(FOP2E(op##q, rdx, rax)) \
+       FOP_END
+
 #define FOP3E(op,  dst, src, src2) \
        FOP_ALIGN #op " %" #src2 ", %" #src ", %" #dst " \n\t" FOP_RET
 
@@ -564,7 +574,8 @@ static int emulate_nm(struct x86_emulate_ctxt *ctxt)
        return emulate_exception(ctxt, NM_VECTOR, 0, false);
 }
 
-static inline void assign_eip_near(struct x86_emulate_ctxt *ctxt, ulong dst)
+static inline int assign_eip_far(struct x86_emulate_ctxt *ctxt, ulong dst,
+                              int cs_l)
 {
        switch (ctxt->op_bytes) {
        case 2:
@@ -573,17 +584,28 @@ static inline void assign_eip_near(struct x86_emulate_ctxt *ctxt, ulong dst)
        case 4:
                ctxt->_eip = (u32)dst;
                break;
+#ifdef CONFIG_X86_64
        case 8:
+               if ((cs_l && is_noncanonical_address(dst)) ||
+                   (!cs_l && (dst >> 32) != 0))
+                       return emulate_gp(ctxt, 0);
                ctxt->_eip = dst;
                break;
+#endif
        default:
                WARN(1, "unsupported eip assignment size\n");
        }
+       return X86EMUL_CONTINUE;
+}
+
+static inline int assign_eip_near(struct x86_emulate_ctxt *ctxt, ulong dst)
+{
+       return assign_eip_far(ctxt, dst, ctxt->mode == X86EMUL_MODE_PROT64);
 }
 
-static inline void jmp_rel(struct x86_emulate_ctxt *ctxt, int rel)
+static inline int jmp_rel(struct x86_emulate_ctxt *ctxt, int rel)
 {
-       assign_eip_near(ctxt, ctxt->_eip + rel);
+       return assign_eip_near(ctxt, ctxt->_eip + rel);
 }
 
 static u16 get_segment_selector(struct x86_emulate_ctxt *ctxt, unsigned seg)
@@ -629,10 +651,11 @@ static bool insn_aligned(struct x86_emulate_ctxt *ctxt, unsigned size)
                return true;
 }
 
-static int __linearize(struct x86_emulate_ctxt *ctxt,
-                    struct segmented_address addr,
-                    unsigned size, bool write, bool fetch,
-                    ulong *linear)
+static __always_inline int __linearize(struct x86_emulate_ctxt *ctxt,
+                                      struct segmented_address addr,
+                                      unsigned *max_size, unsigned size,
+                                      bool write, bool fetch,
+                                      ulong *linear)
 {
        struct desc_struct desc;
        bool usable;
@@ -641,11 +664,17 @@ static int __linearize(struct x86_emulate_ctxt *ctxt,
        u16 sel;
        unsigned cpl;
 
-       la = seg_base(ctxt, addr.seg) + addr.ea;
+       la = seg_base(ctxt, addr.seg) +
+           (fetch || ctxt->ad_bytes == 8 ? addr.ea : (u32)addr.ea);
+       *max_size = 0;
        switch (ctxt->mode) {
        case X86EMUL_MODE_PROT64:
-               if (((signed long)la << 16) >> 16 != la)
+               if (is_noncanonical_address(la))
                        return emulate_gp(ctxt, 0);
+
+               *max_size = min_t(u64, ~0u, (1ull << 48) - la);
+               if (size > *max_size)
+                       goto bad;
                break;
        default:
                usable = ctxt->ops->get_segment(ctxt, &sel, &desc, NULL,
@@ -663,23 +692,28 @@ static int __linearize(struct x86_emulate_ctxt *ctxt,
                if ((ctxt->mode == X86EMUL_MODE_REAL) && !fetch &&
                    (ctxt->d & NoBigReal)) {
                        /* la is between zero and 0xffff */
-                       if (la > 0xffff || (u32)(la + size - 1) > 0xffff)
+                       if (la > 0xffff)
                                goto bad;
+                       *max_size = 0x10000 - la;
                } else if ((desc.type & 8) || !(desc.type & 4)) {
                        /* expand-up segment */
-                       if (addr.ea > lim || (u32)(addr.ea + size - 1) > lim)
+                       if (addr.ea > lim)
                                goto bad;
+                       *max_size = min_t(u64, ~0u, (u64)lim + 1 - addr.ea);
                } else {
                        /* expand-down segment */
-                       if (addr.ea <= lim || (u32)(addr.ea + size - 1) <= lim)
+                       if (addr.ea <= lim)
                                goto bad;
                        lim = desc.d ? 0xffffffff : 0xffff;
-                       if (addr.ea > lim || (u32)(addr.ea + size - 1) > lim)
+                       if (addr.ea > lim)
                                goto bad;
+                       *max_size = min_t(u64, ~0u, (u64)lim + 1 - addr.ea);
                }
+               if (size > *max_size)
+                       goto bad;
                cpl = ctxt->ops->cpl(ctxt);
-               if (!(desc.type & 8)) {
-                       /* data segment */
+               if (!fetch) {
+                       /* data segment or readable code segment */
                        if (cpl > desc.dpl)
                                goto bad;
                } else if ((desc.type & 8) && !(desc.type & 4)) {
@@ -693,7 +727,7 @@ static int __linearize(struct x86_emulate_ctxt *ctxt,
                }
                break;
        }
-       if (fetch ? ctxt->mode != X86EMUL_MODE_PROT64 : ctxt->ad_bytes != 8)
+       if (ctxt->mode != X86EMUL_MODE_PROT64)
                la &= (u32)-1;
        if (insn_aligned(ctxt, size) && ((la & (size - 1)) != 0))
                return emulate_gp(ctxt, 0);
@@ -701,9 +735,9 @@ static int __linearize(struct x86_emulate_ctxt *ctxt,
        return X86EMUL_CONTINUE;
 bad:
        if (addr.seg == VCPU_SREG_SS)
-               return emulate_ss(ctxt, sel);
+               return emulate_ss(ctxt, 0);
        else
-               return emulate_gp(ctxt, sel);
+               return emulate_gp(ctxt, 0);
 }
 
 static int linearize(struct x86_emulate_ctxt *ctxt,
@@ -711,7 +745,8 @@ static int linearize(struct x86_emulate_ctxt *ctxt,
                     unsigned size, bool write,
                     ulong *linear)
 {
-       return __linearize(ctxt, addr, size, write, false, linear);
+       unsigned max_size;
+       return __linearize(ctxt, addr, &max_size, size, write, false, linear);
 }
 
 
@@ -736,17 +771,27 @@ static int segmented_read_std(struct x86_emulate_ctxt *ctxt,
 static int __do_insn_fetch_bytes(struct x86_emulate_ctxt *ctxt, int op_size)
 {
        int rc;
-       unsigned size;
+       unsigned size, max_size;
        unsigned long linear;
        int cur_size = ctxt->fetch.end - ctxt->fetch.data;
        struct segmented_address addr = { .seg = VCPU_SREG_CS,
                                           .ea = ctxt->eip + cur_size };
 
-       size = 15UL ^ cur_size;
-       rc = __linearize(ctxt, addr, size, false, true, &linear);
+       /*
+        * We do not know exactly how many bytes will be needed, and
+        * __linearize is expensive, so fetch as much as possible.  We
+        * just have to avoid going beyond the 15 byte limit, the end
+        * of the segment, or the end of the page.
+        *
+        * __linearize is called with size 0 so that it does not do any
+        * boundary check itself.  Instead, we use max_size to check
+        * against op_size.
+        */
+       rc = __linearize(ctxt, addr, &max_size, 0, false, true, &linear);
        if (unlikely(rc != X86EMUL_CONTINUE))
                return rc;
 
+       size = min_t(unsigned, 15UL ^ cur_size, max_size);
        size = min_t(unsigned, size, PAGE_SIZE - offset_in_page(linear));
 
        /*
@@ -756,7 +801,8 @@ static int __do_insn_fetch_bytes(struct x86_emulate_ctxt *ctxt, int op_size)
         * still, we must have hit the 15-byte boundary.
         */
        if (unlikely(size < op_size))
-               return X86EMUL_UNHANDLEABLE;
+               return emulate_gp(ctxt, 0);
+
        rc = ctxt->ops->fetch(ctxt, linear, ctxt->fetch.end,
                              size, &ctxt->exception);
        if (unlikely(rc != X86EMUL_CONTINUE))
@@ -768,8 +814,10 @@ static int __do_insn_fetch_bytes(struct x86_emulate_ctxt *ctxt, int op_size)
 static __always_inline int do_insn_fetch_bytes(struct x86_emulate_ctxt *ctxt,
                                               unsigned size)
 {
-       if (unlikely(ctxt->fetch.end - ctxt->fetch.ptr < size))
-               return __do_insn_fetch_bytes(ctxt, size);
+       unsigned done_size = ctxt->fetch.end - ctxt->fetch.ptr;
+
+       if (unlikely(done_size < size))
+               return __do_insn_fetch_bytes(ctxt, size - done_size);
        else
                return X86EMUL_CONTINUE;
 }
@@ -874,6 +922,8 @@ FASTOP2W(btc);
 
 FASTOP2(xadd);
 
+FASTOP2R(cmp, cmp_r);
+
 static u8 test_cc(unsigned int condition, unsigned long flags)
 {
        u8 rc;
@@ -1184,6 +1234,7 @@ static int decode_modrm(struct x86_emulate_ctxt *ctxt,
                        if (index_reg != 4)
                                modrm_ea += reg_read(ctxt, index_reg) << scale;
                } else if ((ctxt->modrm_rm & 7) == 5 && ctxt->modrm_mod == 0) {
+                       modrm_ea += insn_fetch(s32, ctxt);
                        if (ctxt->mode == X86EMUL_MODE_PROT64)
                                ctxt->rip_relative = 1;
                } else {
@@ -1192,10 +1243,6 @@ static int decode_modrm(struct x86_emulate_ctxt *ctxt,
                        adjust_modrm_seg(ctxt, base_reg);
                }
                switch (ctxt->modrm_mod) {
-               case 0:
-                       if (ctxt->modrm_rm == 5)
-                               modrm_ea += insn_fetch(s32, ctxt);
-                       break;
                case 1:
                        modrm_ea += insn_fetch(s8, ctxt);
                        break;
@@ -1433,7 +1480,9 @@ static int write_segment_descriptor(struct x86_emulate_ctxt *ctxt,
 
 /* Does not support long mode */
 static int __load_segment_descriptor(struct x86_emulate_ctxt *ctxt,
-                                    u16 selector, int seg, u8 cpl, bool in_task_switch)
+                                    u16 selector, int seg, u8 cpl,
+                                    bool in_task_switch,
+                                    struct desc_struct *desc)
 {
        struct desc_struct seg_desc, old_desc;
        u8 dpl, rpl;
@@ -1571,9 +1620,14 @@ static int __load_segment_descriptor(struct x86_emulate_ctxt *ctxt,
                                sizeof(base3), &ctxt->exception);
                if (ret != X86EMUL_CONTINUE)
                        return ret;
+               if (is_noncanonical_address(get_desc_base(&seg_desc) |
+                                            ((u64)base3 << 32)))
+                       return emulate_gp(ctxt, 0);
        }
 load:
        ctxt->ops->set_segment(ctxt, selector, &seg_desc, base3, seg);
+       if (desc)
+               *desc = seg_desc;
        return X86EMUL_CONTINUE;
 exception:
        return emulate_exception(ctxt, err_vec, err_code, true);
@@ -1583,7 +1637,7 @@ static int load_segment_descriptor(struct x86_emulate_ctxt *ctxt,
                                   u16 selector, int seg)
 {
        u8 cpl = ctxt->ops->cpl(ctxt);
-       return __load_segment_descriptor(ctxt, selector, seg, cpl, false);
+       return __load_segment_descriptor(ctxt, selector, seg, cpl, false, NULL);
 }
 
 static void write_register_operand(struct operand *op)
@@ -1766,6 +1820,10 @@ static int em_push_sreg(struct x86_emulate_ctxt *ctxt)
        int seg = ctxt->src2.val;
 
        ctxt->src.val = get_segment_selector(ctxt, seg);
+       if (ctxt->op_bytes == 4) {
+               rsp_increment(ctxt, -2);
+               ctxt->op_bytes = 2;
+       }
 
        return em_push(ctxt);
 }
@@ -1977,42 +2035,49 @@ static int em_iret(struct x86_emulate_ctxt *ctxt)
 static int em_jmp_far(struct x86_emulate_ctxt *ctxt)
 {
        int rc;
-       unsigned short sel;
+       unsigned short sel, old_sel;
+       struct desc_struct old_desc, new_desc;
+       const struct x86_emulate_ops *ops = ctxt->ops;
+       u8 cpl = ctxt->ops->cpl(ctxt);
+
+       /* Assignment of RIP may only fail in 64-bit mode */
+       if (ctxt->mode == X86EMUL_MODE_PROT64)
+               ops->get_segment(ctxt, &old_sel, &old_desc, NULL,
+                                VCPU_SREG_CS);
 
        memcpy(&sel, ctxt->src.valptr + ctxt->op_bytes, 2);
 
-       rc = load_segment_descriptor(ctxt, sel, VCPU_SREG_CS);
+       rc = __load_segment_descriptor(ctxt, sel, VCPU_SREG_CS, cpl, false,
+                                      &new_desc);
        if (rc != X86EMUL_CONTINUE)
                return rc;
 
-       ctxt->_eip = 0;
-       memcpy(&ctxt->_eip, ctxt->src.valptr, ctxt->op_bytes);
-       return X86EMUL_CONTINUE;
+       rc = assign_eip_far(ctxt, ctxt->src.val, new_desc.l);
+       if (rc != X86EMUL_CONTINUE) {
+               WARN_ON(ctxt->mode != X86EMUL_MODE_PROT64);
+               /* assigning eip failed; restore the old cs */
+               ops->set_segment(ctxt, old_sel, &old_desc, 0, VCPU_SREG_CS);
+               return rc;
+       }
+       return rc;
 }
 
-static int em_grp45(struct x86_emulate_ctxt *ctxt)
+static int em_jmp_abs(struct x86_emulate_ctxt *ctxt)
 {
-       int rc = X86EMUL_CONTINUE;
+       return assign_eip_near(ctxt, ctxt->src.val);
+}
 
-       switch (ctxt->modrm_reg) {
-       case 2: /* call near abs */ {
-               long int old_eip;
-               old_eip = ctxt->_eip;
-               ctxt->_eip = ctxt->src.val;
-               ctxt->src.val = old_eip;
-               rc = em_push(ctxt);
-               break;
-       }
-       case 4: /* jmp abs */
-               ctxt->_eip = ctxt->src.val;
-               break;
-       case 5: /* jmp far */
-               rc = em_jmp_far(ctxt);
-               break;
-       case 6: /* push */
-               rc = em_push(ctxt);
-               break;
-       }
+static int em_call_near_abs(struct x86_emulate_ctxt *ctxt)
+{
+       int rc;
+       long int old_eip;
+
+       old_eip = ctxt->_eip;
+       rc = assign_eip_near(ctxt, ctxt->src.val);
+       if (rc != X86EMUL_CONTINUE)
+               return rc;
+       ctxt->src.val = old_eip;
+       rc = em_push(ctxt);
        return rc;
 }
 
@@ -2039,30 +2104,47 @@ static int em_cmpxchg8b(struct x86_emulate_ctxt *ctxt)
 
 static int em_ret(struct x86_emulate_ctxt *ctxt)
 {
-       ctxt->dst.type = OP_REG;
-       ctxt->dst.addr.reg = &ctxt->_eip;
-       ctxt->dst.bytes = ctxt->op_bytes;
-       return em_pop(ctxt);
+       int rc;
+       unsigned long eip;
+
+       rc = emulate_pop(ctxt, &eip, ctxt->op_bytes);
+       if (rc != X86EMUL_CONTINUE)
+               return rc;
+
+       return assign_eip_near(ctxt, eip);
 }
 
 static int em_ret_far(struct x86_emulate_ctxt *ctxt)
 {
        int rc;
-       unsigned long cs;
+       unsigned long eip, cs;
+       u16 old_cs;
        int cpl = ctxt->ops->cpl(ctxt);
+       struct desc_struct old_desc, new_desc;
+       const struct x86_emulate_ops *ops = ctxt->ops;
 
-       rc = emulate_pop(ctxt, &ctxt->_eip, ctxt->op_bytes);
+       if (ctxt->mode == X86EMUL_MODE_PROT64)
+               ops->get_segment(ctxt, &old_cs, &old_desc, NULL,
+                                VCPU_SREG_CS);
+
+       rc = emulate_pop(ctxt, &eip, ctxt->op_bytes);
        if (rc != X86EMUL_CONTINUE)
                return rc;
-       if (ctxt->op_bytes == 4)
-               ctxt->_eip = (u32)ctxt->_eip;
        rc = emulate_pop(ctxt, &cs, ctxt->op_bytes);
        if (rc != X86EMUL_CONTINUE)
                return rc;
        /* Outer-privilege level return is not implemented */
        if (ctxt->mode >= X86EMUL_MODE_PROT16 && (cs & 3) > cpl)
                return X86EMUL_UNHANDLEABLE;
-       rc = load_segment_descriptor(ctxt, (u16)cs, VCPU_SREG_CS);
+       rc = __load_segment_descriptor(ctxt, (u16)cs, VCPU_SREG_CS, 0, false,
+                                      &new_desc);
+       if (rc != X86EMUL_CONTINUE)
+               return rc;
+       rc = assign_eip_far(ctxt, eip, new_desc.l);
+       if (rc != X86EMUL_CONTINUE) {
+               WARN_ON(ctxt->mode != X86EMUL_MODE_PROT64);
+               ops->set_segment(ctxt, old_cs, &old_desc, 0, VCPU_SREG_CS);
+       }
        return rc;
 }
 
@@ -2242,6 +2324,7 @@ static int em_syscall(struct x86_emulate_ctxt *ctxt)
 
                ops->get_msr(ctxt, MSR_SYSCALL_MASK, &msr_data);
                ctxt->eflags &= ~msr_data;
+               ctxt->eflags |= EFLG_RESERVED_ONE_MASK;
 #endif
        } else {
                /* legacy mode */
@@ -2275,11 +2358,9 @@ static int em_sysenter(struct x86_emulate_ctxt *ctxt)
            && !vendor_intel(ctxt))
                return emulate_ud(ctxt);
 
-       /* XXX sysenter/sysexit have not been tested in 64bit mode.
-       * Therefore, we inject an #UD.
-       */
+       /* sysenter/sysexit have not been tested in 64bit mode. */
        if (ctxt->mode == X86EMUL_MODE_PROT64)
-               return emulate_ud(ctxt);
+               return X86EMUL_UNHANDLEABLE;
 
        setup_syscalls_segments(ctxt, &cs, &ss);
 
@@ -2323,7 +2404,7 @@ static int em_sysexit(struct x86_emulate_ctxt *ctxt)
 {
        const struct x86_emulate_ops *ops = ctxt->ops;
        struct desc_struct cs, ss;
-       u64 msr_data;
+       u64 msr_data, rcx, rdx;
        int usermode;
        u16 cs_sel = 0, ss_sel = 0;
 
@@ -2339,6 +2420,9 @@ static int em_sysexit(struct x86_emulate_ctxt *ctxt)
        else
                usermode = X86EMUL_MODE_PROT32;
 
+       rcx = reg_read(ctxt, VCPU_REGS_RCX);
+       rdx = reg_read(ctxt, VCPU_REGS_RDX);
+
        cs.dpl = 3;
        ss.dpl = 3;
        ops->get_msr(ctxt, MSR_IA32_SYSENTER_CS, &msr_data);
@@ -2348,6 +2432,8 @@ static int em_sysexit(struct x86_emulate_ctxt *ctxt)
                if ((msr_data & 0xfffc) == 0x0)
                        return emulate_gp(ctxt, 0);
                ss_sel = (u16)(msr_data + 24);
+               rcx = (u32)rcx;
+               rdx = (u32)rdx;
                break;
        case X86EMUL_MODE_PROT64:
                cs_sel = (u16)(msr_data + 32);
@@ -2356,6 +2442,9 @@ static int em_sysexit(struct x86_emulate_ctxt *ctxt)
                ss_sel = cs_sel + 8;
                cs.d = 0;
                cs.l = 1;
+               if (is_noncanonical_address(rcx) ||
+                   is_noncanonical_address(rdx))
+                       return emulate_gp(ctxt, 0);
                break;
        }
        cs_sel |= SELECTOR_RPL_MASK;
@@ -2364,8 +2453,8 @@ static int em_sysexit(struct x86_emulate_ctxt *ctxt)
        ops->set_segment(ctxt, cs_sel, &cs, 0, VCPU_SREG_CS);
        ops->set_segment(ctxt, ss_sel, &ss, 0, VCPU_SREG_SS);
 
-       ctxt->_eip = reg_read(ctxt, VCPU_REGS_RDX);
-       *reg_write(ctxt, VCPU_REGS_RSP) = reg_read(ctxt, VCPU_REGS_RCX);
+       ctxt->_eip = rdx;
+       *reg_write(ctxt, VCPU_REGS_RSP) = rcx;
 
        return X86EMUL_CONTINUE;
 }
@@ -2483,19 +2572,24 @@ static int load_state_from_tss16(struct x86_emulate_ctxt *ctxt,
         * Now load segment descriptors. If fault happens at this stage
         * it is handled in a context of new task
         */
-       ret = __load_segment_descriptor(ctxt, tss->ldt, VCPU_SREG_LDTR, cpl, true);
+       ret = __load_segment_descriptor(ctxt, tss->ldt, VCPU_SREG_LDTR, cpl,
+                                       true, NULL);
        if (ret != X86EMUL_CONTINUE)
                return ret;
-       ret = __load_segment_descriptor(ctxt, tss->es, VCPU_SREG_ES, cpl, true);
+       ret = __load_segment_descriptor(ctxt, tss->es, VCPU_SREG_ES, cpl,
+                                       true, NULL);
        if (ret != X86EMUL_CONTINUE)
                return ret;
-       ret = __load_segment_descriptor(ctxt, tss->cs, VCPU_SREG_CS, cpl, true);
+       ret = __load_segment_descriptor(ctxt, tss->cs, VCPU_SREG_CS, cpl,
+                                       true, NULL);
        if (ret != X86EMUL_CONTINUE)
                return ret;
-       ret = __load_segment_descriptor(ctxt, tss->ss, VCPU_SREG_SS, cpl, true);
+       ret = __load_segment_descriptor(ctxt, tss->ss, VCPU_SREG_SS, cpl,
+                                       true, NULL);
        if (ret != X86EMUL_CONTINUE)
                return ret;
-       ret = __load_segment_descriptor(ctxt, tss->ds, VCPU_SREG_DS, cpl, true);
+       ret = __load_segment_descriptor(ctxt, tss->ds, VCPU_SREG_DS, cpl,
+                                       true, NULL);
        if (ret != X86EMUL_CONTINUE)
                return ret;
 
@@ -2620,25 +2714,32 @@ static int load_state_from_tss32(struct x86_emulate_ctxt *ctxt,
         * Now load segment descriptors. If fault happenes at this stage
         * it is handled in a context of new task
         */
-       ret = __load_segment_descriptor(ctxt, tss->ldt_selector, VCPU_SREG_LDTR, cpl, true);
+       ret = __load_segment_descriptor(ctxt, tss->ldt_selector, VCPU_SREG_LDTR,
+                                       cpl, true, NULL);
        if (ret != X86EMUL_CONTINUE)
                return ret;
-       ret = __load_segment_descriptor(ctxt, tss->es, VCPU_SREG_ES, cpl, true);
+       ret = __load_segment_descriptor(ctxt, tss->es, VCPU_SREG_ES, cpl,
+                                       true, NULL);
        if (ret != X86EMUL_CONTINUE)
                return ret;
-       ret = __load_segment_descriptor(ctxt, tss->cs, VCPU_SREG_CS, cpl, true);
+       ret = __load_segment_descriptor(ctxt, tss->cs, VCPU_SREG_CS, cpl,
+                                       true, NULL);
        if (ret != X86EMUL_CONTINUE)
                return ret;
-       ret = __load_segment_descriptor(ctxt, tss->ss, VCPU_SREG_SS, cpl, true);
+       ret = __load_segment_descriptor(ctxt, tss->ss, VCPU_SREG_SS, cpl,
+                                       true, NULL);
        if (ret != X86EMUL_CONTINUE)
                return ret;
-       ret = __load_segment_descriptor(ctxt, tss->ds, VCPU_SREG_DS, cpl, true);
+       ret = __load_segment_descriptor(ctxt, tss->ds, VCPU_SREG_DS, cpl,
+                                       true, NULL);
        if (ret != X86EMUL_CONTINUE)
                return ret;
-       ret = __load_segment_descriptor(ctxt, tss->fs, VCPU_SREG_FS, cpl, true);
+       ret = __load_segment_descriptor(ctxt, tss->fs, VCPU_SREG_FS, cpl,
+                                       true, NULL);
        if (ret != X86EMUL_CONTINUE)
                return ret;
-       ret = __load_segment_descriptor(ctxt, tss->gs, VCPU_SREG_GS, cpl, true);
+       ret = __load_segment_descriptor(ctxt, tss->gs, VCPU_SREG_GS, cpl,
+                                       true, NULL);
        if (ret != X86EMUL_CONTINUE)
                return ret;
 
@@ -2721,7 +2822,8 @@ static int emulator_do_task_switch(struct x86_emulate_ctxt *ctxt,
         *
         * 1. jmp/call/int to task gate: Check against DPL of the task gate
         * 2. Exception/IRQ/iret: No check is performed
-        * 3. jmp/call to TSS: Check against DPL of the TSS
+        * 3. jmp/call to TSS/task-gate: No check is performed since the
+        *    hardware checks it before exiting.
         */
        if (reason == TASK_SWITCH_GATE) {
                if (idt_index != -1) {
@@ -2738,13 +2840,8 @@ static int emulator_do_task_switch(struct x86_emulate_ctxt *ctxt,
                        if ((tss_selector & 3) > dpl || ops->cpl(ctxt) > dpl)
                                return emulate_gp(ctxt, (idt_index << 3) | 0x2);
                }
-       } else if (reason != TASK_SWITCH_IRET) {
-               int dpl = next_tss_desc.dpl;
-               if ((tss_selector & 3) > dpl || ops->cpl(ctxt) > dpl)
-                       return emulate_gp(ctxt, tss_selector);
        }
 
-
        desc_limit = desc_limit_scaled(&next_tss_desc);
        if (!next_tss_desc.p ||
            ((desc_limit < 0x67 && (next_tss_desc.type & 8)) ||
@@ -2905,10 +3002,13 @@ static int em_aad(struct x86_emulate_ctxt *ctxt)
 
 static int em_call(struct x86_emulate_ctxt *ctxt)
 {
+       int rc;
        long rel = ctxt->src.val;
 
        ctxt->src.val = (unsigned long)ctxt->_eip;
-       jmp_rel(ctxt, rel);
+       rc = jmp_rel(ctxt, rel);
+       if (rc != X86EMUL_CONTINUE)
+               return rc;
        return em_push(ctxt);
 }
 
@@ -2917,34 +3017,50 @@ static int em_call_far(struct x86_emulate_ctxt *ctxt)
        u16 sel, old_cs;
        ulong old_eip;
        int rc;
+       struct desc_struct old_desc, new_desc;
+       const struct x86_emulate_ops *ops = ctxt->ops;
+       int cpl = ctxt->ops->cpl(ctxt);
 
-       old_cs = get_segment_selector(ctxt, VCPU_SREG_CS);
        old_eip = ctxt->_eip;
+       ops->get_segment(ctxt, &old_cs, &old_desc, NULL, VCPU_SREG_CS);
 
        memcpy(&sel, ctxt->src.valptr + ctxt->op_bytes, 2);
-       if (load_segment_descriptor(ctxt, sel, VCPU_SREG_CS))
+       rc = __load_segment_descriptor(ctxt, sel, VCPU_SREG_CS, cpl, false,
+                                      &new_desc);
+       if (rc != X86EMUL_CONTINUE)
                return X86EMUL_CONTINUE;
 
-       ctxt->_eip = 0;
-       memcpy(&ctxt->_eip, ctxt->src.valptr, ctxt->op_bytes);
+       rc = assign_eip_far(ctxt, ctxt->src.val, new_desc.l);
+       if (rc != X86EMUL_CONTINUE)
+               goto fail;
 
        ctxt->src.val = old_cs;
        rc = em_push(ctxt);
        if (rc != X86EMUL_CONTINUE)
-               return rc;
+               goto fail;
 
        ctxt->src.val = old_eip;
-       return em_push(ctxt);
+       rc = em_push(ctxt);
+       /* If we failed, we tainted the memory, but the very least we should
+          restore cs */
+       if (rc != X86EMUL_CONTINUE)
+               goto fail;
+       return rc;
+fail:
+       ops->set_segment(ctxt, old_cs, &old_desc, 0, VCPU_SREG_CS);
+       return rc;
+
 }
 
 static int em_ret_near_imm(struct x86_emulate_ctxt *ctxt)
 {
        int rc;
+       unsigned long eip;
 
-       ctxt->dst.type = OP_REG;
-       ctxt->dst.addr.reg = &ctxt->_eip;
-       ctxt->dst.bytes = ctxt->op_bytes;
-       rc = emulate_pop(ctxt, &ctxt->dst.val, ctxt->op_bytes);
+       rc = emulate_pop(ctxt, &eip, ctxt->op_bytes);
+       if (rc != X86EMUL_CONTINUE)
+               return rc;
+       rc = assign_eip_near(ctxt, eip);
        if (rc != X86EMUL_CONTINUE)
                return rc;
        rsp_increment(ctxt, ctxt->src.val);
@@ -3104,6 +3220,8 @@ static int em_mov_rm_sreg(struct x86_emulate_ctxt *ctxt)
                return emulate_ud(ctxt);
 
        ctxt->dst.val = get_segment_selector(ctxt, ctxt->modrm_reg);
+       if (ctxt->dst.bytes == 4 && ctxt->dst.type == OP_MEM)
+               ctxt->dst.bytes = 2;
        return X86EMUL_CONTINUE;
 }
 
@@ -3206,7 +3324,7 @@ static int em_sidt(struct x86_emulate_ctxt *ctxt)
        return emulate_store_desc_ptr(ctxt, ctxt->ops->get_idt);
 }
 
-static int em_lgdt(struct x86_emulate_ctxt *ctxt)
+static int em_lgdt_lidt(struct x86_emulate_ctxt *ctxt, bool lgdt)
 {
        struct desc_ptr desc_ptr;
        int rc;
@@ -3218,12 +3336,23 @@ static int em_lgdt(struct x86_emulate_ctxt *ctxt)
                             ctxt->op_bytes);
        if (rc != X86EMUL_CONTINUE)
                return rc;
-       ctxt->ops->set_gdt(ctxt, &desc_ptr);
+       if (ctxt->mode == X86EMUL_MODE_PROT64 &&
+           is_noncanonical_address(desc_ptr.address))
+               return emulate_gp(ctxt, 0);
+       if (lgdt)
+               ctxt->ops->set_gdt(ctxt, &desc_ptr);
+       else
+               ctxt->ops->set_idt(ctxt, &desc_ptr);
        /* Disable writeback. */
        ctxt->dst.type = OP_NONE;
        return X86EMUL_CONTINUE;
 }
 
+static int em_lgdt(struct x86_emulate_ctxt *ctxt)
+{
+       return em_lgdt_lidt(ctxt, true);
+}
+
 static int em_vmmcall(struct x86_emulate_ctxt *ctxt)
 {
        int rc;
@@ -3237,20 +3366,7 @@ static int em_vmmcall(struct x86_emulate_ctxt *ctxt)
 
 static int em_lidt(struct x86_emulate_ctxt *ctxt)
 {
-       struct desc_ptr desc_ptr;
-       int rc;
-
-       if (ctxt->mode == X86EMUL_MODE_PROT64)
-               ctxt->op_bytes = 8;
-       rc = read_descriptor(ctxt, ctxt->src.addr.mem,
-                            &desc_ptr.size, &desc_ptr.address,
-                            ctxt->op_bytes);
-       if (rc != X86EMUL_CONTINUE)
-               return rc;
-       ctxt->ops->set_idt(ctxt, &desc_ptr);
-       /* Disable writeback. */
-       ctxt->dst.type = OP_NONE;
-       return X86EMUL_CONTINUE;
+       return em_lgdt_lidt(ctxt, false);
 }
 
 static int em_smsw(struct x86_emulate_ctxt *ctxt)
@@ -3271,20 +3387,24 @@ static int em_lmsw(struct x86_emulate_ctxt *ctxt)
 
 static int em_loop(struct x86_emulate_ctxt *ctxt)
 {
+       int rc = X86EMUL_CONTINUE;
+
        register_address_increment(ctxt, reg_rmw(ctxt, VCPU_REGS_RCX), -1);
        if ((address_mask(ctxt, reg_read(ctxt, VCPU_REGS_RCX)) != 0) &&
            (ctxt->b == 0xe2 || test_cc(ctxt->b ^ 0x5, ctxt->eflags)))
-               jmp_rel(ctxt, ctxt->src.val);
+               rc = jmp_rel(ctxt, ctxt->src.val);
 
-       return X86EMUL_CONTINUE;
+       return rc;
 }
 
 static int em_jcxz(struct x86_emulate_ctxt *ctxt)
 {
+       int rc = X86EMUL_CONTINUE;
+
        if (address_mask(ctxt, reg_read(ctxt, VCPU_REGS_RCX)) == 0)
-               jmp_rel(ctxt, ctxt->src.val);
+               rc = jmp_rel(ctxt, ctxt->src.val);
 
-       return X86EMUL_CONTINUE;
+       return rc;
 }
 
 static int em_in(struct x86_emulate_ctxt *ctxt)
@@ -3372,6 +3492,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) {
@@ -3433,7 +3559,7 @@ static int check_cr_write(struct x86_emulate_ctxt *ctxt)
 
                ctxt->ops->get_msr(ctxt, MSR_EFER, &efer);
                if (efer & EFER_LMA)
-                       rsvd = CR3_L_MODE_RESERVED_BITS;
+                       rsvd = CR3_L_MODE_RESERVED_BITS & ~CR3_PCID_INVD;
 
                if (new_val & rsvd)
                        return emulate_gp(ctxt, 0);
@@ -3475,8 +3601,15 @@ static int check_dr_read(struct x86_emulate_ctxt *ctxt)
        if ((cr4 & X86_CR4_DE) && (dr == 4 || dr == 5))
                return emulate_ud(ctxt);
 
-       if (check_dr7_gd(ctxt))
+       if (check_dr7_gd(ctxt)) {
+               ulong dr6;
+
+               ctxt->ops->get_dr(ctxt, 6, &dr6);
+               dr6 &= ~15;
+               dr6 |= DR6_BD | DR6_RTM;
+               ctxt->ops->set_dr(ctxt, 6, dr6);
                return emulate_db(ctxt);
+       }
 
        return X86EMUL_CONTINUE;
 }
@@ -3659,11 +3792,11 @@ static const struct opcode group4[] = {
 static const struct opcode group5[] = {
        F(DstMem | SrcNone | Lock,              em_inc),
        F(DstMem | SrcNone | Lock,              em_dec),
-       I(SrcMem | Stack,                       em_grp45),
+       I(SrcMem | NearBranch,                  em_call_near_abs),
        I(SrcMemFAddr | ImplicitOps | Stack,    em_call_far),
-       I(SrcMem | Stack,                       em_grp45),
-       I(SrcMemFAddr | ImplicitOps,            em_grp45),
-       I(SrcMem | Stack,                       em_grp45), D(Undefined),
+       I(SrcMem | NearBranch,                  em_jmp_abs),
+       I(SrcMemFAddr | ImplicitOps,            em_jmp_far),
+       I(SrcMem | Stack,                       em_push), D(Undefined),
 };
 
 static const struct opcode group6[] = {
@@ -3710,6 +3843,16 @@ static const struct opcode group11[] = {
        X7(D(Undefined)),
 };
 
+static const struct gprefix pfx_0f_ae_7 = {
+       I(SrcMem | ByteOp, 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),
 };
@@ -3833,7 +3976,7 @@ static const struct opcode opcode_table[256] = {
        I2bvIP(DstDI | SrcDX | Mov | String | Unaligned, em_in, ins, check_perm_in), /* insb, insw/insd */
        I2bvIP(SrcSI | DstDX | String, em_out, outs, check_perm_out), /* outsb, outsw/outsd */
        /* 0x70 - 0x7F */
-       X16(D(SrcImmByte)),
+       X16(D(SrcImmByte | NearBranch)),
        /* 0x80 - 0x87 */
        G(ByteOp | DstMem | SrcImm, group1),
        G(DstMem | SrcImm, group1),
@@ -3860,20 +4003,20 @@ static const struct opcode opcode_table[256] = {
        I2bv(DstAcc | SrcMem | Mov | MemAbs, em_mov),
        I2bv(DstMem | SrcAcc | Mov | MemAbs | PageTable, em_mov),
        I2bv(SrcSI | DstDI | Mov | String, em_mov),
-       F2bv(SrcSI | DstDI | String | NoWrite, em_cmp),
+       F2bv(SrcSI | DstDI | String | NoWrite, em_cmp_r),
        /* 0xA8 - 0xAF */
        F2bv(DstAcc | SrcImm | NoWrite, em_test),
        I2bv(SrcAcc | DstDI | Mov | String, em_mov),
        I2bv(SrcSI | DstAcc | Mov | String, em_mov),
-       F2bv(SrcAcc | DstDI | String | NoWrite, em_cmp),
+       F2bv(SrcAcc | DstDI | String | NoWrite, em_cmp_r),
        /* 0xB0 - 0xB7 */
        X8(I(ByteOp | DstReg | SrcImm | Mov, em_mov)),
        /* 0xB8 - 0xBF */
        X8(I(DstReg | SrcImm64 | Mov, em_mov)),
        /* 0xC0 - 0xC7 */
        G(ByteOp | Src2ImmByte, group2), G(Src2ImmByte, group2),
-       I(ImplicitOps | Stack | SrcImmU16, em_ret_near_imm),
-       I(ImplicitOps | Stack, em_ret),
+       I(ImplicitOps | NearBranch | SrcImmU16, em_ret_near_imm),
+       I(ImplicitOps | NearBranch, em_ret),
        I(DstReg | SrcMemFAddr | ModRM | No64 | Src2ES, em_lseg),
        I(DstReg | SrcMemFAddr | ModRM | No64 | Src2DS, em_lseg),
        G(ByteOp, group11), G(0, group11),
@@ -3893,13 +4036,14 @@ static const struct opcode opcode_table[256] = {
        /* 0xD8 - 0xDF */
        N, E(0, &escape_d9), N, E(0, &escape_db), N, E(0, &escape_dd), N, N,
        /* 0xE0 - 0xE7 */
-       X3(I(SrcImmByte, em_loop)),
-       I(SrcImmByte, em_jcxz),
+       X3(I(SrcImmByte | NearBranch, em_loop)),
+       I(SrcImmByte | NearBranch, em_jcxz),
        I2bvIP(SrcImmUByte | DstAcc, em_in,  in,  check_perm_in),
        I2bvIP(SrcAcc | DstImmUByte, em_out, out, check_perm_out),
        /* 0xE8 - 0xEF */
-       I(SrcImm | Stack, em_call), D(SrcImm | ImplicitOps),
-       I(SrcImmFAddr | No64, em_jmp_far), D(SrcImmByte | ImplicitOps),
+       I(SrcImm | NearBranch, em_call), D(SrcImm | ImplicitOps | NearBranch),
+       I(SrcImmFAddr | No64, em_jmp_far),
+       D(SrcImmByte | ImplicitOps | NearBranch),
        I2bvIP(SrcDX | DstAcc, em_in,  in,  check_perm_in),
        I2bvIP(SrcAcc | DstDX, em_out, out, check_perm_out),
        /* 0xF0 - 0xF7 */
@@ -3918,10 +4062,11 @@ static const struct opcode twobyte_table[256] = {
        N, I(ImplicitOps | EmulateOnUD, em_syscall),
        II(ImplicitOps | Priv, em_clts, clts), N,
        DI(ImplicitOps | Priv, invd), DI(ImplicitOps | Priv, wbinvd), N, N,
-       N, D(ImplicitOps | ModRM), N, N,
+       N, D(ImplicitOps | ModRM | SrcMem | NoAccess), N, N,
        /* 0x10 - 0x1F */
        N, N, N, N, N, N, N, N,
-       D(ImplicitOps | ModRM), N, N, N, N, N, N, D(ImplicitOps | ModRM),
+       D(ImplicitOps | ModRM | SrcMem | NoAccess),
+       N, N, N, N, N, N, D(ImplicitOps | ModRM | SrcMem | NoAccess),
        /* 0x20 - 0x2F */
        DIP(ModRM | DstMem | Priv | Op3264 | NoMod, cr_read, check_cr_read),
        DIP(ModRM | DstMem | Priv | Op3264 | NoMod, dr_read, check_dr_read),
@@ -3958,7 +4103,7 @@ static const struct opcode twobyte_table[256] = {
        N, N, N, N,
        N, N, N, GP(SrcReg | DstMem | ModRM | Mov, &pfx_0f_6f_0f_7f),
        /* 0x80 - 0x8F */
-       X16(D(SrcImm)),
+       X16(D(SrcImm | NearBranch)),
        /* 0x90 - 0x9F */
        X16(D(ByteOp | DstMem | SrcNone | ModRM| Mov)),
        /* 0xA0 - 0xA7 */
@@ -3973,7 +4118,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),
@@ -4370,8 +4515,7 @@ done_prefixes:
 
        /* vex-prefix instructions are not implemented */
        if (ctxt->opcode_len == 1 && (ctxt->b == 0xc5 || ctxt->b == 0xc4) &&
-           (mode == X86EMUL_MODE_PROT64 ||
-           (mode >= X86EMUL_MODE_PROT16 && (ctxt->modrm & 0x80)))) {
+           (mode == X86EMUL_MODE_PROT64 || (ctxt->modrm & 0xc0) == 0xc0)) {
                ctxt->d = NotImpl;
        }
 
@@ -4427,7 +4571,7 @@ done_prefixes:
                return EMULATION_FAILED;
 
        if (unlikely(ctxt->d &
-                    (NotImpl|Stack|Op3264|Sse|Mmx|Intercept|CheckPerm))) {
+           (NotImpl|Stack|Op3264|Sse|Mmx|Intercept|CheckPerm|NearBranch))) {
                /*
                 * These are copied unconditionally here, and checked unconditionally
                 * in x86_emulate_insn.
@@ -4438,8 +4582,12 @@ done_prefixes:
                if (ctxt->d & NotImpl)
                        return EMULATION_FAILED;
 
-               if (mode == X86EMUL_MODE_PROT64 && (ctxt->d & Stack))
-                       ctxt->op_bytes = 8;
+               if (mode == X86EMUL_MODE_PROT64) {
+                       if (ctxt->op_bytes == 4 && (ctxt->d & Stack))
+                               ctxt->op_bytes = 8;
+                       else if (ctxt->d & NearBranch)
+                               ctxt->op_bytes = 8;
+               }
 
                if (ctxt->d & Op3264) {
                        if (mode == X86EMUL_MODE_PROT64)
@@ -4490,10 +4638,10 @@ done_prefixes:
        /* Decode and fetch the destination operand: register or memory. */
        rc = decode_operand(ctxt, &ctxt->dst, (ctxt->d >> DstShift) & OpMask);
 
-done:
        if (ctxt->rip_relative)
                ctxt->memopp->addr.mem.ea += ctxt->_eip;
 
+done:
        return (rc != X86EMUL_CONTINUE) ? EMULATION_FAILED : EMULATION_OK;
 }
 
@@ -4743,7 +4891,7 @@ special_insn:
                break;
        case 0x70 ... 0x7f: /* jcc (short) */
                if (test_cc(ctxt->b, ctxt->eflags))
-                       jmp_rel(ctxt, ctxt->src.val);
+                       rc = jmp_rel(ctxt, ctxt->src.val);
                break;
        case 0x8d: /* lea r16/r32, m */
                ctxt->dst.val = ctxt->src.addr.mem.ea;
@@ -4773,7 +4921,7 @@ special_insn:
                break;
        case 0xe9: /* jmp rel */
        case 0xeb: /* jmp rel short */
-               jmp_rel(ctxt, ctxt->src.val);
+               rc = jmp_rel(ctxt, ctxt->src.val);
                ctxt->dst.type = OP_NONE; /* Disable writeback. */
                break;
        case 0xf4:              /* hlt */
@@ -4898,13 +5046,11 @@ twobyte_insn:
                break;
        case 0x80 ... 0x8f: /* jnz rel, etc*/
                if (test_cc(ctxt->b, ctxt->eflags))
-                       jmp_rel(ctxt, ctxt->src.val);
+                       rc = jmp_rel(ctxt, ctxt->src.val);
                break;
        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