diff options
author | Takuya Yoshikawa <yoshikawa.takuya@oss.ntt.co.jp> | 2011-11-22 01:20:47 -0500 |
---|---|---|
committer | Avi Kivity <avi@redhat.com> | 2011-12-27 04:17:31 -0500 |
commit | e940b5c20f89282fe826c5e2237932ab280497cf (patch) | |
tree | 94ae1350f5260033039764f0ac5f106765136536 /arch | |
parent | e1e210b0a7f7b4d14577bdc76719963f7facc0e7 (diff) |
KVM: x86 emulator: Use opcode::execute for CMPXCHG
CMPXCHG: 0F B0, 0F B1
Signed-off-by: Takuya Yoshikawa <yoshikawa.takuya@oss.ntt.co.jp>
Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/x86/kvm/emulate.c | 37 |
1 files changed, 19 insertions, 18 deletions
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c index 906c5eb34aa7..799000d8bf8b 100644 --- a/arch/x86/kvm/emulate.c +++ b/arch/x86/kvm/emulate.c | |||
@@ -1832,6 +1832,24 @@ static int em_ret_far(struct x86_emulate_ctxt *ctxt) | |||
1832 | return rc; | 1832 | return rc; |
1833 | } | 1833 | } |
1834 | 1834 | ||
1835 | static int em_cmpxchg(struct x86_emulate_ctxt *ctxt) | ||
1836 | { | ||
1837 | /* Save real source value, then compare EAX against destination. */ | ||
1838 | ctxt->src.orig_val = ctxt->src.val; | ||
1839 | ctxt->src.val = ctxt->regs[VCPU_REGS_RAX]; | ||
1840 | emulate_2op_SrcV(ctxt, "cmp"); | ||
1841 | |||
1842 | if (ctxt->eflags & EFLG_ZF) { | ||
1843 | /* Success: write back to memory. */ | ||
1844 | ctxt->dst.val = ctxt->src.orig_val; | ||
1845 | } else { | ||
1846 | /* Failure: write the value we saw to EAX. */ | ||
1847 | ctxt->dst.type = OP_REG; | ||
1848 | ctxt->dst.addr.reg = (unsigned long *)&ctxt->regs[VCPU_REGS_RAX]; | ||
1849 | } | ||
1850 | return X86EMUL_CONTINUE; | ||
1851 | } | ||
1852 | |||
1835 | static int em_lseg(struct x86_emulate_ctxt *ctxt) | 1853 | static int em_lseg(struct x86_emulate_ctxt *ctxt) |
1836 | { | 1854 | { |
1837 | int seg = ctxt->src2.val; | 1855 | int seg = ctxt->src2.val; |
@@ -3400,7 +3418,7 @@ static struct opcode twobyte_table[256] = { | |||
3400 | D(DstMem | SrcReg | Src2CL | ModRM), | 3418 | D(DstMem | SrcReg | Src2CL | ModRM), |
3401 | D(ModRM), I(DstReg | SrcMem | ModRM, em_imul), | 3419 | D(ModRM), I(DstReg | SrcMem | ModRM, em_imul), |
3402 | /* 0xB0 - 0xB7 */ | 3420 | /* 0xB0 - 0xB7 */ |
3403 | D2bv(DstMem | SrcReg | ModRM | Lock | PageTable), | 3421 | I2bv(DstMem | SrcReg | ModRM | Lock | PageTable, em_cmpxchg), |
3404 | I(DstReg | SrcMemFAddr | ModRM | Src2SS, em_lseg), | 3422 | I(DstReg | SrcMemFAddr | ModRM | Src2SS, em_lseg), |
3405 | I(DstMem | SrcReg | ModRM | BitOp | Lock, em_btr), | 3423 | I(DstMem | SrcReg | ModRM | BitOp | Lock, em_btr), |
3406 | I(DstReg | SrcMemFAddr | ModRM | Src2FS, em_lseg), | 3424 | I(DstReg | SrcMemFAddr | ModRM | Src2FS, em_lseg), |
@@ -4153,23 +4171,6 @@ twobyte_insn: | |||
4153 | break; | 4171 | break; |
4154 | case 0xae: /* clflush */ | 4172 | case 0xae: /* clflush */ |
4155 | break; | 4173 | break; |
4156 | case 0xb0 ... 0xb1: /* cmpxchg */ | ||
4157 | /* | ||
4158 | * Save real source value, then compare EAX against | ||
4159 | * destination. | ||
4160 | */ | ||
4161 | ctxt->src.orig_val = ctxt->src.val; | ||
4162 | ctxt->src.val = ctxt->regs[VCPU_REGS_RAX]; | ||
4163 | emulate_2op_SrcV(ctxt, "cmp"); | ||
4164 | if (ctxt->eflags & EFLG_ZF) { | ||
4165 | /* Success: write back to memory. */ | ||
4166 | ctxt->dst.val = ctxt->src.orig_val; | ||
4167 | } else { | ||
4168 | /* Failure: write the value we saw to EAX. */ | ||
4169 | ctxt->dst.type = OP_REG; | ||
4170 | ctxt->dst.addr.reg = (unsigned long *)&ctxt->regs[VCPU_REGS_RAX]; | ||
4171 | } | ||
4172 | break; | ||
4173 | case 0xb6 ... 0xb7: /* movzx */ | 4174 | case 0xb6 ... 0xb7: /* movzx */ |
4174 | ctxt->dst.bytes = ctxt->op_bytes; | 4175 | ctxt->dst.bytes = ctxt->op_bytes; |
4175 | ctxt->dst.val = (ctxt->d & ByteOp) ? (u8) ctxt->src.val | 4176 | ctxt->dst.val = (ctxt->d & ByteOp) ? (u8) ctxt->src.val |