KVM: x86 emulator: add get_cached_segment_base() callback to x86_emulate_ops
[deliverable/linux.git] / arch / x86 / kvm / emulate.c
index ab3fff5bf7c467637bf53c34eac874d1ba627389..8228778ace38111b31561886335f1273e30fc765 100644 (file)
@@ -52,6 +52,7 @@
 #define DstMem      (3<<1)     /* Memory operand. */
 #define DstAcc      (4<<1)      /* Destination Accumulator */
 #define DstDI       (5<<1)     /* Destination is in ES:(E)DI */
+#define DstMem64    (6<<1)     /* 64bit memory operand */
 #define DstMask     (7<<1)
 /* Source operand type. */
 #define SrcNone     (0<<4)     /* No source operand. */
@@ -66,6 +67,8 @@
 #define SrcImmUByte (8<<4)      /* 8-bit unsigned immediate operand. */
 #define SrcImmU     (9<<4)      /* Immediate operand, unsigned */
 #define SrcSI       (0xa<<4)   /* Source is in the DS:RSI */
+#define SrcImmFAddr (0xb<<4)   /* Source is immediate far address */
+#define SrcMemFAddr (0xc<<4)   /* Source is far address in memory */
 #define SrcMask     (0xf<<4)
 /* Generic ModRM decode. */
 #define ModRM       (1<<8)
 #define Src2CL      (1<<29)
 #define Src2ImmByte (2<<29)
 #define Src2One     (3<<29)
-#define Src2Imm16   (4<<29)
-#define Src2Mem16   (5<<29) /* Used for Ep encoding. First argument has to be
-                              in memory and second argument is located
-                              immediately after the first one in memory. */
 #define Src2Mask    (7<<29)
 
 enum {
@@ -170,11 +169,11 @@ static u32 opcode_table[256] = {
        ByteOp | DstMem | SrcReg | ModRM | Mov, DstMem | SrcReg | ModRM | Mov,
        ByteOp | DstReg | SrcMem | ModRM | Mov, DstReg | SrcMem | ModRM | Mov,
        DstMem | SrcReg | ModRM | Mov, ModRM | DstReg,
-       DstReg | SrcMem | ModRM | Mov, Group | Group1A,
+       ImplicitOps | SrcMem | ModRM, Group | Group1A,
        /* 0x90 - 0x97 */
        DstReg, DstReg, DstReg, DstReg, DstReg, DstReg, DstReg, DstReg,
        /* 0x98 - 0x9F */
-       0, 0, SrcImm | Src2Imm16 | No64, 0,
+       0, 0, SrcImmFAddr | No64, 0,
        ImplicitOps | Stack, ImplicitOps | Stack, 0, 0,
        /* 0xA0 - 0xA7 */
        ByteOp | DstReg | SrcMem | Mov | MemAbs, DstReg | SrcMem | Mov | MemAbs,
@@ -214,7 +213,7 @@ static u32 opcode_table[256] = {
        ByteOp | SrcImmUByte | DstAcc, SrcImmUByte | DstAcc,
        /* 0xE8 - 0xEF */
        SrcImm | Stack, SrcImm | ImplicitOps,
-       SrcImmU | Src2Imm16 | No64, SrcImmByte | ImplicitOps,
+       SrcImmFAddr | No64, SrcImmByte | ImplicitOps,
        SrcNone | ByteOp | DstAcc, SrcNone | DstAcc,
        SrcNone | ByteOp | DstAcc, SrcNone | DstAcc,
        /* 0xF0 - 0xF7 */
@@ -349,7 +348,7 @@ static u32 group_table[] = {
        [Group5*8] =
        DstMem | SrcNone | ModRM, DstMem | SrcNone | ModRM,
        SrcMem | ModRM | Stack, 0,
-       SrcMem | ModRM | Stack, SrcMem | ModRM | Src2Mem16 | ImplicitOps,
+       SrcMem | ModRM | Stack, SrcMemFAddr | ModRM | ImplicitOps,
        SrcMem | ModRM | Stack, 0,
        [Group7*8] =
        0, 0, ModRM | SrcMem | Priv, ModRM | SrcMem | Priv,
@@ -360,7 +359,7 @@ static u32 group_table[] = {
        DstMem | SrcImmByte | ModRM, DstMem | SrcImmByte | ModRM | Lock,
        DstMem | SrcImmByte | ModRM | Lock, DstMem | SrcImmByte | ModRM | Lock,
        [Group9*8] =
-       0, ImplicitOps | ModRM | Lock, 0, 0, 0, 0, 0, 0,
+       0, DstMem64 | ModRM | Lock, 0, 0, 0, 0, 0, 0,
 };
 
 static u32 group2_table[] = {
@@ -575,6 +574,13 @@ static u32 group2_table[] = {
        (_type)_x;                                                      \
 })
 
+#define insn_fetch_arr(_arr, _size, _eip)                                \
+({     rc = do_insn_fetch(ctxt, ops, (_eip), _arr, (_size));           \
+       if (rc != X86EMUL_CONTINUE)                                     \
+               goto done;                                              \
+       (_eip) += (_size);                                              \
+})
+
 static inline unsigned long ad_mask(struct decode_cache *c)
 {
        return (1UL << (c->ad_bytes << 3)) - 1;
@@ -645,21 +651,22 @@ static unsigned long ss_base(struct x86_emulate_ctxt *ctxt)
 
 static int do_fetch_insn_byte(struct x86_emulate_ctxt *ctxt,
                              struct x86_emulate_ops *ops,
-                             unsigned long linear, u8 *dest)
+                             unsigned long eip, u8 *dest)
 {
        struct fetch_cache *fc = &ctxt->decode.fetch;
        int rc;
-       int size;
+       int size, cur_size;
 
-       if (linear < fc->start || linear >= fc->end) {
-               size = min(15UL, PAGE_SIZE - offset_in_page(linear));
-               rc = ops->fetch(linear, fc->data, size, ctxt->vcpu, NULL);
+       if (eip == fc->end) {
+               cur_size = fc->end - fc->start;
+               size = min(15UL - cur_size, PAGE_SIZE - offset_in_page(eip));
+               rc = ops->fetch(ctxt->cs_base + eip, fc->data + cur_size,
+                               size, ctxt->vcpu, NULL);
                if (rc != X86EMUL_CONTINUE)
                        return rc;
-               fc->start = linear;
-               fc->end = linear + size;
+               fc->end += size;
        }
-       *dest = fc->data[linear - fc->start];
+       *dest = fc->data[eip - fc->start];
        return X86EMUL_CONTINUE;
 }
 
@@ -672,7 +679,6 @@ static int do_insn_fetch(struct x86_emulate_ctxt *ctxt,
        /* x86 instructions are limited to 15 bytes. */
        if (eip + size - ctxt->eip > 15)
                return X86EMUL_UNHANDLEABLE;
-       eip += ctxt->cs_base;
        while (size--) {
                rc = do_fetch_insn_byte(ctxt, ops, eip++, dest++);
                if (rc != X86EMUL_CONTINUE)
@@ -934,6 +940,7 @@ x86_decode_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
        /* Shadow copy of register state. Committed on successful emulation. */
        memset(c, 0, sizeof(struct decode_cache));
        c->eip = ctxt->eip;
+       c->fetch.start = c->fetch.end = c->eip;
        ctxt->cs_base = seg_base(ctxt, VCPU_SREG_CS);
        memcpy(c->regs, ctxt->vcpu->arch.regs, sizeof c->regs);
 
@@ -1158,6 +1165,17 @@ done_prefixes:
                                         c->regs[VCPU_REGS_RSI]);
                c->src.val = 0;
                break;
+       case SrcImmFAddr:
+               c->src.type = OP_IMM;
+               c->src.ptr = (unsigned long *)c->eip;
+               c->src.bytes = c->op_bytes + 2;
+               insn_fetch_arr(c->src.valptr, c->src.bytes, c->eip);
+               break;
+       case SrcMemFAddr:
+               c->src.type = OP_MEM;
+               c->src.ptr = (unsigned long *)c->modrm_ea;
+               c->src.bytes = c->op_bytes + 2;
+               break;
        }
 
        /*
@@ -1177,22 +1195,10 @@ done_prefixes:
                c->src2.bytes = 1;
                c->src2.val = insn_fetch(u8, 1, c->eip);
                break;
-       case Src2Imm16:
-               c->src2.type = OP_IMM;
-               c->src2.ptr = (unsigned long *)c->eip;
-               c->src2.bytes = 2;
-               c->src2.val = insn_fetch(u16, 2, c->eip);
-               break;
        case Src2One:
                c->src2.bytes = 1;
                c->src2.val = 1;
                break;
-       case Src2Mem16:
-               c->src2.type = OP_MEM;
-               c->src2.bytes = 2;
-               c->src2.ptr = (unsigned long *)(c->modrm_ea + c->src.bytes);
-               c->src2.val = 0;
-               break;
        }
 
        /* Decode and fetch the destination operand: register or memory. */
@@ -1205,6 +1211,7 @@ done_prefixes:
                         c->twobyte && (c->b == 0xb6 || c->b == 0xb7));
                break;
        case DstMem:
+       case DstMem64:
                if ((c->d & ModRM) && c->modrm_mod == 3) {
                        c->dst.bytes = (c->d & ByteOp) ? 1 : c->op_bytes;
                        c->dst.type = OP_REG;
@@ -1214,7 +1221,10 @@ done_prefixes:
                }
                c->dst.type = OP_MEM;
                c->dst.ptr = (unsigned long *)c->modrm_ea;
-               c->dst.bytes = (c->d & ByteOp) ? 1 : c->op_bytes;
+               if ((c->d & DstMask) == DstMem64)
+                       c->dst.bytes = 8;
+               else
+                       c->dst.bytes = (c->d & ByteOp) ? 1 : c->op_bytes;
                c->dst.val = 0;
                if (c->d & BitOp) {
                        unsigned long mask = ~(c->dst.bytes * 8 - 1);
@@ -1257,6 +1267,33 @@ done:
        return (rc == X86EMUL_UNHANDLEABLE) ? -1 : 0;
 }
 
+static int read_emulated(struct x86_emulate_ctxt *ctxt,
+                        struct x86_emulate_ops *ops,
+                        unsigned long addr, void *dest, unsigned size)
+{
+       int rc;
+       struct read_cache *mc = &ctxt->decode.mem_read;
+
+       while (size) {
+               int n = min(size, 8u);
+               size -= n;
+               if (mc->pos < mc->end)
+                       goto read_cached;
+
+               rc = ops->read_emulated(addr, mc->data + mc->end, n, ctxt->vcpu);
+               if (rc != X86EMUL_CONTINUE)
+                       return rc;
+               mc->end += n;
+
+       read_cached:
+               memcpy(dest, mc->data + mc->pos, n);
+               mc->pos += n;
+               dest += n;
+               addr += n;
+       }
+       return X86EMUL_CONTINUE;
+}
+
 static int pio_in_emulated(struct x86_emulate_ctxt *ctxt,
                           struct x86_emulate_ops *ops,
                           unsigned int size, unsigned short port,
@@ -1498,9 +1535,9 @@ static int emulate_pop(struct x86_emulate_ctxt *ctxt,
        struct decode_cache *c = &ctxt->decode;
        int rc;
 
-       rc = ops->read_emulated(register_address(c, ss_base(ctxt),
-                                                c->regs[VCPU_REGS_RSP]),
-                               dest, len, ctxt->vcpu);
+       rc = read_emulated(ctxt, ops, register_address(c, ss_base(ctxt),
+                                                      c->regs[VCPU_REGS_RSP]),
+                          dest, len);
        if (rc != X86EMUL_CONTINUE)
                return rc;
 
@@ -1706,12 +1743,7 @@ static inline int emulate_grp9(struct x86_emulate_ctxt *ctxt,
                               struct x86_emulate_ops *ops)
 {
        struct decode_cache *c = &ctxt->decode;
-       u64 old, new;
-       int rc;
-
-       rc = ops->read_emulated(c->modrm_ea, &old, 8, ctxt->vcpu);
-       if (rc != X86EMUL_CONTINUE)
-               return rc;
+       u64 old = c->dst.orig_val;
 
        if (((u32) (old >> 0) != (u32) c->regs[VCPU_REGS_RAX]) ||
            ((u32) (old >> 32) != (u32) c->regs[VCPU_REGS_RDX])) {
@@ -1719,14 +1751,10 @@ static inline int emulate_grp9(struct x86_emulate_ctxt *ctxt,
                c->regs[VCPU_REGS_RAX] = (u32) (old >> 0);
                c->regs[VCPU_REGS_RDX] = (u32) (old >> 32);
                ctxt->eflags &= ~EFLG_ZF;
-
        } else {
-               new = ((u64)c->regs[VCPU_REGS_RCX] << 32) |
+               c->dst.val = ((u64)c->regs[VCPU_REGS_RCX] << 32) |
                       (u32) c->regs[VCPU_REGS_RBX];
 
-               rc = ops->cmpxchg_emulated(c->modrm_ea, &old, &new, 8, ctxt->vcpu);
-               if (rc != X86EMUL_CONTINUE)
-                       return rc;
                ctxt->eflags |= EFLG_ZF;
        }
        return X86EMUL_CONTINUE;
@@ -1847,7 +1875,7 @@ setup_syscalls_segments(struct x86_emulate_ctxt *ctxt,
 }
 
 static int
-emulate_syscall(struct x86_emulate_ctxt *ctxt)
+emulate_syscall(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
 {
        struct decode_cache *c = &ctxt->decode;
        struct kvm_segment cs, ss;
@@ -1862,7 +1890,7 @@ emulate_syscall(struct x86_emulate_ctxt *ctxt)
 
        setup_syscalls_segments(ctxt, &cs, &ss);
 
-       kvm_x86_ops->get_msr(ctxt->vcpu, MSR_STAR, &msr_data);
+       ops->get_msr(ctxt->vcpu, MSR_STAR, &msr_data);
        msr_data >>= 32;
        cs.selector = (u16)(msr_data & 0xfffc);
        ss.selector = (u16)(msr_data + 8);
@@ -1879,17 +1907,17 @@ emulate_syscall(struct x86_emulate_ctxt *ctxt)
 #ifdef CONFIG_X86_64
                c->regs[VCPU_REGS_R11] = ctxt->eflags & ~EFLG_RF;
 
-               kvm_x86_ops->get_msr(ctxt->vcpu,
-                       ctxt->mode == X86EMUL_MODE_PROT64 ?
-                       MSR_LSTAR : MSR_CSTAR, &msr_data);
+               ops->get_msr(ctxt->vcpu,
+                            ctxt->mode == X86EMUL_MODE_PROT64 ?
+                            MSR_LSTAR : MSR_CSTAR, &msr_data);
                c->eip = msr_data;
 
-               kvm_x86_ops->get_msr(ctxt->vcpu, MSR_SYSCALL_MASK, &msr_data);
+               ops->get_msr(ctxt->vcpu, MSR_SYSCALL_MASK, &msr_data);
                ctxt->eflags &= ~(msr_data | EFLG_RF);
 #endif
        } else {
                /* legacy mode */
-               kvm_x86_ops->get_msr(ctxt->vcpu, MSR_STAR, &msr_data);
+               ops->get_msr(ctxt->vcpu, MSR_STAR, &msr_data);
                c->eip = (u32)msr_data;
 
                ctxt->eflags &= ~(EFLG_VM | EFLG_IF | EFLG_RF);
@@ -1899,7 +1927,7 @@ emulate_syscall(struct x86_emulate_ctxt *ctxt)
 }
 
 static int
-emulate_sysenter(struct x86_emulate_ctxt *ctxt)
+emulate_sysenter(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
 {
        struct decode_cache *c = &ctxt->decode;
        struct kvm_segment cs, ss;
@@ -1921,7 +1949,7 @@ emulate_sysenter(struct x86_emulate_ctxt *ctxt)
 
        setup_syscalls_segments(ctxt, &cs, &ss);
 
-       kvm_x86_ops->get_msr(ctxt->vcpu, MSR_IA32_SYSENTER_CS, &msr_data);
+       ops->get_msr(ctxt->vcpu, MSR_IA32_SYSENTER_CS, &msr_data);
        switch (ctxt->mode) {
        case X86EMUL_MODE_PROT32:
                if ((msr_data & 0xfffc) == 0x0) {
@@ -1951,17 +1979,17 @@ emulate_sysenter(struct x86_emulate_ctxt *ctxt)
        kvm_x86_ops->set_segment(ctxt->vcpu, &cs, VCPU_SREG_CS);
        kvm_x86_ops->set_segment(ctxt->vcpu, &ss, VCPU_SREG_SS);
 
-       kvm_x86_ops->get_msr(ctxt->vcpu, MSR_IA32_SYSENTER_EIP, &msr_data);
+       ops->get_msr(ctxt->vcpu, MSR_IA32_SYSENTER_EIP, &msr_data);
        c->eip = msr_data;
 
-       kvm_x86_ops->get_msr(ctxt->vcpu, MSR_IA32_SYSENTER_ESP, &msr_data);
+       ops->get_msr(ctxt->vcpu, MSR_IA32_SYSENTER_ESP, &msr_data);
        c->regs[VCPU_REGS_RSP] = msr_data;
 
        return X86EMUL_CONTINUE;
 }
 
 static int
-emulate_sysexit(struct x86_emulate_ctxt *ctxt)
+emulate_sysexit(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
 {
        struct decode_cache *c = &ctxt->decode;
        struct kvm_segment cs, ss;
@@ -1984,7 +2012,7 @@ emulate_sysexit(struct x86_emulate_ctxt *ctxt)
 
        cs.dpl = 3;
        ss.dpl = 3;
-       kvm_x86_ops->get_msr(ctxt->vcpu, MSR_IA32_SYSENTER_CS, &msr_data);
+       ops->get_msr(ctxt->vcpu, MSR_IA32_SYSENTER_CS, &msr_data);
        switch (usermode) {
        case X86EMUL_MODE_PROT32:
                cs.selector = (u16)(msr_data + 16);
@@ -2069,17 +2097,6 @@ static bool emulator_io_permited(struct x86_emulate_ctxt *ctxt,
        return true;
 }
 
-static u32 get_cached_descriptor_base(struct x86_emulate_ctxt *ctxt,
-                                     struct x86_emulate_ops *ops,
-                                     int seg)
-{
-       struct desc_struct desc;
-       if (ops->get_cached_descriptor(&desc, seg, ctxt->vcpu))
-               return get_desc_base(&desc);
-       else
-               return ~0;
-}
-
 static void save_state_to_tss16(struct x86_emulate_ctxt *ctxt,
                                struct x86_emulate_ops *ops,
                                struct tss_segment_16 *tss)
@@ -2347,14 +2364,15 @@ static int task_switch_32(struct x86_emulate_ctxt *ctxt,
 }
 
 static int emulator_do_task_switch(struct x86_emulate_ctxt *ctxt,
-                                   struct x86_emulate_ops *ops,
-                                   u16 tss_selector, int reason)
+                                  struct x86_emulate_ops *ops,
+                                  u16 tss_selector, int reason,
+                                  bool has_error_code, u32 error_code)
 {
        struct desc_struct curr_tss_desc, next_tss_desc;
        int ret;
        u16 old_tss_sel = ops->get_segment_selector(VCPU_SREG_TR, ctxt->vcpu);
        ulong old_tss_base =
-               get_cached_descriptor_base(ctxt, ops, VCPU_SREG_TR);
+               ops->get_cached_segment_base(VCPU_SREG_TR, ctxt->vcpu);
        u32 desc_limit;
 
        /* FIXME: old_tss_base == ~0 ? */
@@ -2405,6 +2423,8 @@ static int emulator_do_task_switch(struct x86_emulate_ctxt *ctxt,
        else
                ret = task_switch_16(ctxt, ops, tss_selector, old_tss_sel,
                                     old_tss_base, &next_tss_desc);
+       if (ret != X86EMUL_CONTINUE)
+               return ret;
 
        if (reason == TASK_SWITCH_CALL || reason == TASK_SWITCH_GATE)
                ctxt->eflags = ctxt->eflags | X86_EFLAGS_NT;
@@ -2419,12 +2439,22 @@ static int emulator_do_task_switch(struct x86_emulate_ctxt *ctxt,
        ops->set_cached_descriptor(&next_tss_desc, VCPU_SREG_TR, ctxt->vcpu);
        ops->set_segment_selector(tss_selector, VCPU_SREG_TR, ctxt->vcpu);
 
+       if (has_error_code) {
+               struct decode_cache *c = &ctxt->decode;
+
+               c->op_bytes = c->ad_bytes = (next_tss_desc.type & 8) ? 4 : 2;
+               c->lock_prefix = 0;
+               c->src.val = (unsigned long) error_code;
+               emulate_push(ctxt);
+       }
+
        return ret;
 }
 
 int emulator_task_switch(struct x86_emulate_ctxt *ctxt,
                         struct x86_emulate_ops *ops,
-                        u16 tss_selector, int reason)
+                        u16 tss_selector, int reason,
+                        bool has_error_code, u32 error_code)
 {
        struct decode_cache *c = &ctxt->decode;
        int rc;
@@ -2432,15 +2462,18 @@ int emulator_task_switch(struct x86_emulate_ctxt *ctxt,
        memset(c, 0, sizeof(struct decode_cache));
        c->eip = ctxt->eip;
        memcpy(c->regs, ctxt->vcpu->arch.regs, sizeof c->regs);
+       c->dst.type = OP_NONE;
 
-       rc = emulator_do_task_switch(ctxt, ops, tss_selector, reason);
+       rc = emulator_do_task_switch(ctxt, ops, tss_selector, reason,
+                                    has_error_code, error_code);
 
        if (rc == X86EMUL_CONTINUE) {
                memcpy(ctxt->vcpu->arch.regs, c->regs, sizeof c->regs);
                kvm_rip_write(ctxt->vcpu, c->eip);
+               rc = writeback(ctxt, ops);
        }
 
-       return rc;
+       return (rc == X86EMUL_UNHANDLEABLE) ? -1 : 0;
 }
 
 static void string_addr_inc(struct x86_emulate_ctxt *ctxt, unsigned long base,
@@ -2462,6 +2495,7 @@ x86_emulate_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
        int saved_dst_type = c->dst.type;
 
        ctxt->interruptibility = 0;
+       ctxt->decode.mem_read.pos = 0;
 
        /* Shadow copy of register state. Committed on successful emulation.
         * NOTE: we can copy them from vcpu as x86_decode_insn() doesn't
@@ -2516,20 +2550,16 @@ x86_emulate_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
        }
 
        if (c->src.type == OP_MEM) {
-               rc = ops->read_emulated((unsigned long)c->src.ptr,
-                                       &c->src.val,
-                                       c->src.bytes,
-                                       ctxt->vcpu);
+               rc = read_emulated(ctxt, ops, (unsigned long)c->src.ptr,
+                                       c->src.valptr, c->src.bytes);
                if (rc != X86EMUL_CONTINUE)
                        goto done;
                c->src.orig_val = c->src.val;
        }
 
        if (c->src2.type == OP_MEM) {
-               rc = ops->read_emulated((unsigned long)c->src2.ptr,
-                                       &c->src2.val,
-                                       c->src2.bytes,
-                                       ctxt->vcpu);
+               rc = read_emulated(ctxt, ops, (unsigned long)c->src2.ptr,
+                                       &c->src2.val, c->src2.bytes);
                if (rc != X86EMUL_CONTINUE)
                        goto done;
        }
@@ -2540,8 +2570,8 @@ x86_emulate_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
 
        if ((c->dst.type == OP_MEM) && !(c->d & Mov)) {
                /* optimisation - avoid slow emulated read if Mov */
-               rc = ops->read_emulated((unsigned long)c->dst.ptr, &c->dst.val,
-                                       c->dst.bytes, ctxt->vcpu);
+               rc = read_emulated(ctxt, ops, (unsigned long)c->dst.ptr,
+                                  &c->dst.val, c->dst.bytes);
                if (rc != X86EMUL_CONTINUE)
                        goto done;
        }
@@ -2762,13 +2792,13 @@ special_insn:
                        goto done;
                break;
        case 0x90: /* nop / xchg r8,rax */
-               if (!(c->rex_prefix & 1)) { /* nop */
-                       c->dst.type = OP_NONE;
+               if (c->dst.ptr == (unsigned long *)&c->regs[VCPU_REGS_RAX]) {
+                       c->dst.type = OP_NONE;  /* nop */
                        break;
                }
        case 0x91 ... 0x97: /* xchg reg,rax */
-               c->src.type = c->dst.type = OP_REG;
-               c->src.bytes = c->dst.bytes = c->op_bytes;
+               c->src.type = OP_REG;
+               c->src.bytes = c->op_bytes;
                c->src.ptr = (unsigned long *) &c->regs[VCPU_REGS_RAX];
                c->src.val = *(c->src.ptr);
                goto xchg;
@@ -2847,14 +2877,18 @@ special_insn:
        }
        case 0xe9: /* jmp rel */
                goto jmp;
-       case 0xea: /* jmp far */
+       case 0xea: { /* jmp far */
+               unsigned short sel;
        jump_far:
-               if (load_segment_descriptor(ctxt, ops, c->src2.val,
-                                           VCPU_SREG_CS))
+               memcpy(&sel, c->src.valptr + c->op_bytes, 2);
+
+               if (load_segment_descriptor(ctxt, ops, sel, VCPU_SREG_CS))
                        goto done;
 
-               c->eip = c->src.val;
+               c->eip = 0;
+               memcpy(&c->eip, c->src.valptr, c->op_bytes);
                break;
+       }
        case 0xeb:
              jmp:              /* jmp rel short */
                jmp_rel(c, c->src.val);
@@ -2968,10 +3002,15 @@ writeback:
                    (rc->end != 0 && rc->end == rc->pos))
                        ctxt->restart = false;
        }
-
+       /*
+        * reset read cache here in case string instruction is restared
+        * without decoding
+        */
+       ctxt->decode.mem_read.end = 0;
        /* Commit shadow register state. */
        memcpy(ctxt->vcpu->arch.regs, c->regs, sizeof c->regs);
        kvm_rip_write(ctxt->vcpu, c->eip);
+       ops->set_rflags(ctxt->vcpu, ctxt->eflags);
 
 done:
        return (rc == X86EMUL_UNHANDLEABLE) ? -1 : 0;
@@ -3049,7 +3088,7 @@ twobyte_insn:
                }
                break;
        case 0x05:              /* syscall */
-               rc = emulate_syscall(ctxt);
+               rc = emulate_syscall(ctxt, ops);
                if (rc != X86EMUL_CONTINUE)
                        goto done;
                else
@@ -3082,7 +3121,7 @@ twobyte_insn:
                        kvm_queue_exception(ctxt->vcpu, UD_VECTOR);
                        goto done;
                }
-               emulator_get_dr(ctxt, c->modrm_reg, &c->regs[c->modrm_rm]);
+               ops->get_dr(c->modrm_reg, &c->regs[c->modrm_rm], ctxt->vcpu);
                c->dst.type = OP_NONE;  /* no writeback */
                break;
        case 0x22: /* mov reg, cr */
@@ -3095,14 +3134,17 @@ twobyte_insn:
                        kvm_queue_exception(ctxt->vcpu, UD_VECTOR);
                        goto done;
                }
-               emulator_set_dr(ctxt, c->modrm_reg, c->regs[c->modrm_rm]);
+
+               ops->set_dr(c->modrm_reg,c->regs[c->modrm_rm] &
+                           ((ctxt->mode == X86EMUL_MODE_PROT64) ? ~0ULL : ~0U),
+                       ctxt->vcpu);
                c->dst.type = OP_NONE;  /* no writeback */
                break;
        case 0x30:
                /* wrmsr */
                msr_data = (u32)c->regs[VCPU_REGS_RAX]
                        | ((u64)c->regs[VCPU_REGS_RDX] << 32);
-               if (kvm_set_msr(ctxt->vcpu, c->regs[VCPU_REGS_RCX], msr_data)) {
+               if (ops->set_msr(ctxt->vcpu, c->regs[VCPU_REGS_RCX], msr_data)) {
                        kvm_inject_gp(ctxt->vcpu, 0);
                        goto done;
                }
@@ -3111,7 +3153,7 @@ twobyte_insn:
                break;
        case 0x32:
                /* rdmsr */
-               if (kvm_get_msr(ctxt->vcpu, c->regs[VCPU_REGS_RCX], &msr_data)) {
+               if (ops->get_msr(ctxt->vcpu, c->regs[VCPU_REGS_RCX], &msr_data)) {
                        kvm_inject_gp(ctxt->vcpu, 0);
                        goto done;
                } else {
@@ -3122,14 +3164,14 @@ twobyte_insn:
                c->dst.type = OP_NONE;
                break;
        case 0x34:              /* sysenter */
-               rc = emulate_sysenter(ctxt);
+               rc = emulate_sysenter(ctxt, ops);
                if (rc != X86EMUL_CONTINUE)
                        goto done;
                else
                        goto writeback;
                break;
        case 0x35:              /* sysexit */
-               rc = emulate_sysexit(ctxt);
+               rc = emulate_sysexit(ctxt, ops);
                if (rc != X86EMUL_CONTINUE)
                        goto done;
                else
@@ -3244,7 +3286,6 @@ twobyte_insn:
                rc = emulate_grp9(ctxt, ops);
                if (rc != X86EMUL_CONTINUE)
                        goto done;
-               c->dst.type = OP_NONE;
                break;
        }
        goto writeback;
This page took 0.048019 seconds and 5 git commands to generate.