KVM: x86 emulator: Use opcode::execute for CMPXCHG
authorTakuya Yoshikawa <yoshikawa.takuya@oss.ntt.co.jp>
Tue, 22 Nov 2011 06:20:47 +0000 (15:20 +0900)
committerAvi Kivity <avi@redhat.com>
Tue, 27 Dec 2011 09:17:31 +0000 (11:17 +0200)
CMPXCHG: 0F B0, 0F B1

Signed-off-by: Takuya Yoshikawa <yoshikawa.takuya@oss.ntt.co.jp>
Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
arch/x86/kvm/emulate.c

index 906c5eb34aa7960628d7c0d021a060e94cc9b378..799000d8bf8b44a1afd5069af9afc5c1e62e67f3 100644 (file)
@@ -1832,6 +1832,24 @@ static int em_ret_far(struct x86_emulate_ctxt *ctxt)
        return rc;
 }
 
+static int em_cmpxchg(struct x86_emulate_ctxt *ctxt)
+{
+       /* Save real source value, then compare EAX against destination. */
+       ctxt->src.orig_val = ctxt->src.val;
+       ctxt->src.val = ctxt->regs[VCPU_REGS_RAX];
+       emulate_2op_SrcV(ctxt, "cmp");
+
+       if (ctxt->eflags & EFLG_ZF) {
+               /* Success: write back to memory. */
+               ctxt->dst.val = ctxt->src.orig_val;
+       } else {
+               /* Failure: write the value we saw to EAX. */
+               ctxt->dst.type = OP_REG;
+               ctxt->dst.addr.reg = (unsigned long *)&ctxt->regs[VCPU_REGS_RAX];
+       }
+       return X86EMUL_CONTINUE;
+}
+
 static int em_lseg(struct x86_emulate_ctxt *ctxt)
 {
        int seg = ctxt->src2.val;
@@ -3400,7 +3418,7 @@ static struct opcode twobyte_table[256] = {
        D(DstMem | SrcReg | Src2CL | ModRM),
        D(ModRM), I(DstReg | SrcMem | ModRM, em_imul),
        /* 0xB0 - 0xB7 */
-       D2bv(DstMem | SrcReg | ModRM | Lock | PageTable),
+       I2bv(DstMem | SrcReg | ModRM | Lock | PageTable, em_cmpxchg),
        I(DstReg | SrcMemFAddr | ModRM | Src2SS, em_lseg),
        I(DstMem | SrcReg | ModRM | BitOp | Lock, em_btr),
        I(DstReg | SrcMemFAddr | ModRM | Src2FS, em_lseg),
@@ -4153,23 +4171,6 @@ twobyte_insn:
                break;
        case 0xae:              /* clflush */
                break;
-       case 0xb0 ... 0xb1:     /* cmpxchg */
-               /*
-                * Save real source value, then compare EAX against
-                * destination.
-                */
-               ctxt->src.orig_val = ctxt->src.val;
-               ctxt->src.val = ctxt->regs[VCPU_REGS_RAX];
-               emulate_2op_SrcV(ctxt, "cmp");
-               if (ctxt->eflags & EFLG_ZF) {
-                       /* Success: write back to memory. */
-                       ctxt->dst.val = ctxt->src.orig_val;
-               } else {
-                       /* Failure: write the value we saw to EAX. */
-                       ctxt->dst.type = OP_REG;
-                       ctxt->dst.addr.reg = (unsigned long *)&ctxt->regs[VCPU_REGS_RAX];
-               }
-               break;
        case 0xb6 ... 0xb7:     /* movzx */
                ctxt->dst.bytes = ctxt->op_bytes;
                ctxt->dst.val = (ctxt->d & ByteOp) ? (u8) ctxt->src.val