KVM: Change the emulator_{read,write,cmpxchg}_* functions to take a vcpu
[linux-2.6-block.git] / drivers / kvm / x86_emulate.c
index 4b8a0cc9665eda6662c5248782ec846e1e6367e7..44eb28d31499c080616a5a53ee2d52f70027288b 100644 (file)
@@ -6,7 +6,7 @@
  * Copyright (c) 2005 Keir Fraser
  *
  * Linux coding style, mod r/m decoder, segment base fixes, real-mode
- * privieged instructions:
+ * privileged instructions:
  *
  * Copyright (C) 2006 Qumranet
  *
@@ -420,7 +420,7 @@ struct operand {
 #define insn_fetch(_type, _size, _eip)                                  \
 ({     unsigned long _x;                                               \
        rc = ops->read_std((unsigned long)(_eip) + ctxt->cs_base, &_x,  \
-                                                  (_size), ctxt);       \
+                                                  (_size), ctxt->vcpu); \
        if ( rc != 0 )                                                  \
                goto done;                                              \
        (_eip) += (_size);                                              \
@@ -443,8 +443,13 @@ struct operand {
                           (((reg) + _inc) & ((1UL << (ad_bytes << 3)) - 1)); \
        } while (0)
 
-void *decode_register(u8 modrm_reg, unsigned long *regs,
-                     int highbyte_regs)
+/*
+ * Given the 'reg' portion of a ModRM byte, and a register block, return a
+ * pointer into the block that addresses the relevant register.
+ * @highbyte_regs specifies whether to decode AH,CH,DH,BH.
+ */
+static void *decode_register(u8 modrm_reg, unsigned long *regs,
+                            int highbyte_regs)
 {
        void *p;
 
@@ -464,10 +469,12 @@ static int read_descriptor(struct x86_emulate_ctxt *ctxt,
        if (op_bytes == 2)
                op_bytes = 3;
        *address = 0;
-       rc = ops->read_std((unsigned long)ptr, (unsigned long *)size, 2, ctxt);
+       rc = ops->read_std((unsigned long)ptr, (unsigned long *)size, 2,
+                          ctxt->vcpu);
        if (rc)
                return rc;
-       rc = ops->read_std((unsigned long)ptr + 2, address, op_bytes, ctxt);
+       rc = ops->read_std((unsigned long)ptr + 2, address, op_bytes,
+                          ctxt->vcpu);
        return rc;
 }
 
@@ -775,7 +782,7 @@ done_prefixes:
                src.type = OP_MEM;
                src.ptr = (unsigned long *)cr2;
                if ((rc = ops->read_emulated((unsigned long)src.ptr,
-                                            &src.val, src.bytes, ctxt)) != 0)
+                                            &src.val, src.bytes, ctxt->vcpu)) != 0)
                        goto done;
                src.orig_val = src.val;
                break;
@@ -814,7 +821,7 @@ done_prefixes:
        case DstReg:
                dst.type = OP_REG;
                if ((d & ByteOp)
-                   && !(twobyte_table && (b == 0xb6 || b == 0xb7))) {
+                   && !(twobyte && (b == 0xb6 || b == 0xb7))) {
                        dst.ptr = decode_register(modrm_reg, _regs,
                                                  (rex_prefix == 0));
                        dst.val = *(u8 *) dst.ptr;
@@ -845,7 +852,7 @@ done_prefixes:
                }
                if (!(d & Mov) && /* optimisation - avoid slow emulated read */
                    ((rc = ops->read_emulated((unsigned long)dst.ptr,
-                                             &dst.val, dst.bytes, ctxt)) != 0))
+                                             &dst.val, dst.bytes, ctxt->vcpu)) != 0))
                        goto done;
                break;
        }
@@ -958,7 +965,7 @@ done_prefixes:
                        dst.bytes = 8;
                if ((rc = ops->read_std(register_address(ctxt->ss_base,
                                                         _regs[VCPU_REGS_RSP]),
-                                       &dst.val, dst.bytes, ctxt)) != 0)
+                                       &dst.val, dst.bytes, ctxt->vcpu)) != 0)
                        goto done;
                register_address_increment(_regs[VCPU_REGS_RSP], dst.bytes);
                break;
@@ -1043,7 +1050,7 @@ done_prefixes:
                                dst.bytes = 8;
                                if ((rc = ops->read_std((unsigned long)dst.ptr,
                                                        &dst.val, 8,
-                                                       ctxt)) != 0)
+                                                       ctxt->vcpu)) != 0)
                                        goto done;
                        }
                        register_address_increment(_regs[VCPU_REGS_RSP],
@@ -1051,7 +1058,7 @@ done_prefixes:
                        if ((rc = ops->write_std(
                                     register_address(ctxt->ss_base,
                                                      _regs[VCPU_REGS_RSP]),
-                                    &dst.val, dst.bytes, ctxt)) != 0)
+                                    &dst.val, dst.bytes, ctxt->vcpu)) != 0)
                                goto done;
                        no_wb = 1;
                        break;
@@ -1086,11 +1093,11 @@ writeback:
                                rc = ops->cmpxchg_emulated((unsigned long)dst.
                                                           ptr, &dst.orig_val,
                                                           &dst.val, dst.bytes,
-                                                          ctxt);
+                                                          ctxt->vcpu);
                        else
                                rc = ops->write_emulated((unsigned long)dst.ptr,
                                                         &dst.val, dst.bytes,
-                                                        ctxt);
+                                                        ctxt->vcpu);
                        if (rc != 0)
                                goto done;
                default:
@@ -1125,7 +1132,7 @@ special_insn:
                                                        _regs[VCPU_REGS_RDI]);
                if ((rc = ops->read_emulated(register_address(
                      override_base ? *override_base : ctxt->ds_base,
-                     _regs[VCPU_REGS_RSI]), &dst.val, dst.bytes, ctxt)) != 0)
+                     _regs[VCPU_REGS_RSI]), &dst.val, dst.bytes, ctxt->vcpu)) != 0)
                        goto done;
                register_address_increment(_regs[VCPU_REGS_RSI],
                             (_eflags & EFLG_DF) ? -dst.bytes : dst.bytes);
@@ -1147,7 +1154,8 @@ special_insn:
                dst.type = OP_REG;
                dst.bytes = (d & ByteOp) ? 1 : op_bytes;
                dst.ptr = (unsigned long *)&_regs[VCPU_REGS_RAX];
-               if ((rc = ops->read_emulated(cr2, &dst.val, dst.bytes, ctxt)) != 0)
+               if ((rc = ops->read_emulated(cr2, &dst.val, dst.bytes,
+                                            ctxt->vcpu)) != 0)
                        goto done;
                register_address_increment(_regs[VCPU_REGS_RSI],
                           (_eflags & EFLG_DF) ? -dst.bytes : dst.bytes);
@@ -1166,7 +1174,8 @@ special_insn:
 
 pop_instruction:
                if ((rc = ops->read_std(register_address(ctxt->ss_base,
-                       _regs[VCPU_REGS_RSP]), dst.ptr, op_bytes, ctxt)) != 0)
+                       _regs[VCPU_REGS_RSP]), dst.ptr, op_bytes, ctxt->vcpu))
+                       != 0)
                        goto done;
 
                register_address_increment(_regs[VCPU_REGS_RSP], op_bytes);
@@ -1230,40 +1239,40 @@ twobyte_insn:
                break;
        case 0x40 ... 0x4f:     /* cmov */
                dst.val = dst.orig_val = src.val;
-               d &= ~Mov;      /* default to no move */
+               no_wb = 1;
                /*
                 * First, assume we're decoding an even cmov opcode
                 * (lsb == 0).
                 */
                switch ((b & 15) >> 1) {
                case 0: /* cmovo */
-                       d |= (_eflags & EFLG_OF) ? Mov : 0;
+                       no_wb = (_eflags & EFLG_OF) ? 0 : 1;
                        break;
                case 1: /* cmovb/cmovc/cmovnae */
-                       d |= (_eflags & EFLG_CF) ? Mov : 0;
+                       no_wb = (_eflags & EFLG_CF) ? 0 : 1;
                        break;
                case 2: /* cmovz/cmove */
-                       d |= (_eflags & EFLG_ZF) ? Mov : 0;
+                       no_wb = (_eflags & EFLG_ZF) ? 0 : 1;
                        break;
                case 3: /* cmovbe/cmovna */
-                       d |= (_eflags & (EFLG_CF | EFLG_ZF)) ? Mov : 0;
+                       no_wb = (_eflags & (EFLG_CF | EFLG_ZF)) ? 0 : 1;
                        break;
                case 4: /* cmovs */
-                       d |= (_eflags & EFLG_SF) ? Mov : 0;
+                       no_wb = (_eflags & EFLG_SF) ? 0 : 1;
                        break;
                case 5: /* cmovp/cmovpe */
-                       d |= (_eflags & EFLG_PF) ? Mov : 0;
+                       no_wb = (_eflags & EFLG_PF) ? 0 : 1;
                        break;
                case 7: /* cmovle/cmovng */
-                       d |= (_eflags & EFLG_ZF) ? Mov : 0;
+                       no_wb = (_eflags & EFLG_ZF) ? 0 : 1;
                        /* fall through */
                case 6: /* cmovl/cmovnge */
-                       d |= (!(_eflags & EFLG_SF) !=
-                             !(_eflags & EFLG_OF)) ? Mov : 0;
+                       no_wb &= (!(_eflags & EFLG_SF) !=
+                             !(_eflags & EFLG_OF)) ? 0 : 1;
                        break;
                }
                /* Odd cmov opcodes (lsb == 1) have inverted sense. */
-               d ^= (b & 1) ? Mov : 0;
+               no_wb ^= b & 1;
                break;
        case 0xb0 ... 0xb1:     /* cmpxchg */
                /*
@@ -1273,8 +1282,6 @@ twobyte_insn:
                src.orig_val = src.val;
                src.val = _regs[VCPU_REGS_RAX];
                emulate_2op_SrcV("cmp", src, dst, _eflags);
-               /* Always write back. The question is: where to? */
-               d |= Mov;
                if (_eflags & EFLG_ZF) {
                        /* Success: write back to memory. */
                        dst.val = src.orig_val;
@@ -1375,7 +1382,8 @@ twobyte_special_insn:
        case 0xc7:              /* Grp9 (cmpxchg8b) */
                {
                        u64 old, new;
-                       if ((rc = ops->read_emulated(cr2, &old, 8, ctxt)) != 0)
+                       if ((rc = ops->read_emulated(cr2, &old, 8, ctxt->vcpu))
+                                                                       != 0)
                                goto done;
                        if (((u32) (old >> 0) != (u32) _regs[VCPU_REGS_RAX]) ||
                            ((u32) (old >> 32) != (u32) _regs[VCPU_REGS_RDX])) {
@@ -1386,7 +1394,7 @@ twobyte_special_insn:
                                new = ((u64)_regs[VCPU_REGS_RCX] << 32)
                                        | (u32) _regs[VCPU_REGS_RBX];
                                if ((rc = ops->cmpxchg_emulated(cr2, &old,
-                                                         &new, 8, ctxt)) != 0)
+                                                         &new, 8, ctxt->vcpu)) != 0)
                                        goto done;
                                _eflags |= EFLG_ZF;
                        }