]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/kvm/x86_emulate.c
Merge master.kernel.org:/pub/scm/linux/kernel/git/lethal/sh-2.6.23
[linux-2.6-omap-h63xx.git] / drivers / kvm / x86_emulate.c
index 46c38063a1024aa1f41872e9dd780a93f7ddffa6..1f979cb0df314f82cab71e88f2c7892922454860 100644 (file)
@@ -131,9 +131,9 @@ static u8 opcode_table[256] = {
        /* 0xB0 - 0xBF */
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        /* 0xC0 - 0xC7 */
-       ByteOp | DstMem | SrcImm | ModRM, DstMem | SrcImmByte | ModRM, 0, 0,
-       0, 0, ByteOp | DstMem | SrcImm | ModRM | Mov,
-           DstMem | SrcImm | ModRM | Mov,
+       ByteOp | DstMem | SrcImm | ModRM, DstMem | SrcImmByte | ModRM,
+       0, ImplicitOps, 0, 0,
+       ByteOp | DstMem | SrcImm | ModRM | Mov, DstMem | SrcImm | ModRM | Mov,
        /* 0xC8 - 0xCF */
        0, 0, 0, 0, 0, 0, 0, 0,
        /* 0xD0 - 0xD7 */
@@ -163,7 +163,7 @@ static u16 twobyte_table[256] = {
        ModRM | ImplicitOps, ModRM, ModRM | ImplicitOps, ModRM, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0,
        /* 0x30 - 0x3F */
-       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       ImplicitOps, 0, ImplicitOps, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        /* 0x40 - 0x47 */
        DstReg | SrcMem | ModRM | Mov, DstReg | SrcMem | ModRM | Mov,
        DstReg | SrcMem | ModRM | Mov, DstReg | SrcMem | ModRM | Mov,
@@ -485,6 +485,8 @@ x86_emulate_memop(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
        int mode = ctxt->mode;
        unsigned long modrm_ea;
        int use_modrm_ea, index_reg = 0, base_reg = 0, scale, rip_relative = 0;
+       int no_wb = 0;
+       u64 msr_data;
 
        /* Shadow copy of register state. Committed on successful emulation. */
        unsigned long _regs[NR_VCPU_REGS];
@@ -1051,7 +1053,7 @@ done_prefixes:
                                                      _regs[VCPU_REGS_RSP]),
                                     &dst.val, dst.bytes, ctxt)) != 0)
                                goto done;
-                       dst.val = dst.orig_val; /* skanky: disable writeback */
+                       no_wb = 1;
                        break;
                default:
                        goto cannot_emulate;
@@ -1060,7 +1062,7 @@ done_prefixes:
        }
 
 writeback:
-       if ((d & Mov) || (dst.orig_val != dst.val)) {
+       if (!no_wb) {
                switch (dst.type) {
                case OP_REG:
                        /* The 4-byte case *is* correct: in 64-bit mode we zero-extend. */
@@ -1156,15 +1158,19 @@ special_insn:
        case 0xf4:              /* hlt */
                ctxt->vcpu->halt_request = 1;
                goto done;
+       case 0xc3: /* ret */
+               dst.ptr = &_eip;
+               goto pop_instruction;
        case 0x58 ... 0x5f: /* pop reg */
                dst.ptr = (unsigned long *)&_regs[b & 0x7];
 
+pop_instruction:
                if ((rc = ops->read_std(register_address(ctxt->ss_base,
                        _regs[VCPU_REGS_RSP]), dst.ptr, op_bytes, ctxt)) != 0)
                        goto done;
 
-               register_address_increment(_regs[VCPU_REGS_RSP], dst.bytes);
-               dst.orig_val = dst.val; /* Disable writeback. */
+               register_address_increment(_regs[VCPU_REGS_RSP], op_bytes);
+               no_wb = 1; /* Disable writeback. */
                break;
        }
        goto writeback;
@@ -1172,6 +1178,8 @@ special_insn:
 twobyte_insn:
        switch (b) {
        case 0x01: /* lgdt, lidt, lmsw */
+               /* Disable writeback. */
+               no_wb = 1;
                switch (modrm_reg) {
                        u16 size;
                        unsigned long address;
@@ -1319,7 +1327,7 @@ twobyte_insn:
 
 twobyte_special_insn:
        /* Disable writeback. */
-       dst.orig_val = dst.val;
+       no_wb = 1;
        switch (b) {
        case 0x09:              /* wbinvd */
                break;
@@ -1339,6 +1347,29 @@ twobyte_special_insn:
                        goto cannot_emulate;
                realmode_set_cr(ctxt->vcpu, modrm_reg, modrm_val, &_eflags);
                break;
+       case 0x30:
+               /* wrmsr */
+               msr_data = (u32)_regs[VCPU_REGS_RAX]
+                       | ((u64)_regs[VCPU_REGS_RDX] << 32);
+               rc = kvm_set_msr(ctxt->vcpu, _regs[VCPU_REGS_RCX], msr_data);
+               if (rc) {
+                       kvm_arch_ops->inject_gp(ctxt->vcpu, 0);
+                       _eip = ctxt->vcpu->rip;
+               }
+               rc = X86EMUL_CONTINUE;
+               break;
+       case 0x32:
+               /* rdmsr */
+               rc = kvm_get_msr(ctxt->vcpu, _regs[VCPU_REGS_RCX], &msr_data);
+               if (rc) {
+                       kvm_arch_ops->inject_gp(ctxt->vcpu, 0);
+                       _eip = ctxt->vcpu->rip;
+               } else {
+                       _regs[VCPU_REGS_RAX] = (u32)msr_data;
+                       _regs[VCPU_REGS_RDX] = msr_data >> 32;
+               }
+               rc = X86EMUL_CONTINUE;
+               break;
        case 0xc7:              /* Grp9 (cmpxchg8b) */
                {
                        u64 old, new;