diff options
| -rw-r--r-- | arch/x86/kvm/emulate.c | 24 |
1 files changed, 10 insertions, 14 deletions
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c index 48de4b890055..b8ce53861f68 100644 --- a/arch/x86/kvm/emulate.c +++ b/arch/x86/kvm/emulate.c | |||
| @@ -52,6 +52,7 @@ | |||
| 52 | #define DstMem (3<<1) /* Memory operand. */ | 52 | #define DstMem (3<<1) /* Memory operand. */ |
| 53 | #define DstAcc (4<<1) /* Destination Accumulator */ | 53 | #define DstAcc (4<<1) /* Destination Accumulator */ |
| 54 | #define DstDI (5<<1) /* Destination is in ES:(E)DI */ | 54 | #define DstDI (5<<1) /* Destination is in ES:(E)DI */ |
| 55 | #define DstMem64 (6<<1) /* 64bit memory operand */ | ||
| 55 | #define DstMask (7<<1) | 56 | #define DstMask (7<<1) |
| 56 | /* Source operand type. */ | 57 | /* Source operand type. */ |
| 57 | #define SrcNone (0<<4) /* No source operand. */ | 58 | #define SrcNone (0<<4) /* No source operand. */ |
| @@ -360,7 +361,7 @@ static u32 group_table[] = { | |||
| 360 | DstMem | SrcImmByte | ModRM, DstMem | SrcImmByte | ModRM | Lock, | 361 | DstMem | SrcImmByte | ModRM, DstMem | SrcImmByte | ModRM | Lock, |
| 361 | DstMem | SrcImmByte | ModRM | Lock, DstMem | SrcImmByte | ModRM | Lock, | 362 | DstMem | SrcImmByte | ModRM | Lock, DstMem | SrcImmByte | ModRM | Lock, |
| 362 | [Group9*8] = | 363 | [Group9*8] = |
| 363 | 0, ImplicitOps | ModRM | Lock, 0, 0, 0, 0, 0, 0, | 364 | 0, DstMem64 | ModRM | Lock, 0, 0, 0, 0, 0, 0, |
| 364 | }; | 365 | }; |
| 365 | 366 | ||
| 366 | static u32 group2_table[] = { | 367 | static u32 group2_table[] = { |
| @@ -1205,6 +1206,7 @@ done_prefixes: | |||
| 1205 | c->twobyte && (c->b == 0xb6 || c->b == 0xb7)); | 1206 | c->twobyte && (c->b == 0xb6 || c->b == 0xb7)); |
| 1206 | break; | 1207 | break; |
| 1207 | case DstMem: | 1208 | case DstMem: |
| 1209 | case DstMem64: | ||
| 1208 | if ((c->d & ModRM) && c->modrm_mod == 3) { | 1210 | if ((c->d & ModRM) && c->modrm_mod == 3) { |
| 1209 | c->dst.bytes = (c->d & ByteOp) ? 1 : c->op_bytes; | 1211 | c->dst.bytes = (c->d & ByteOp) ? 1 : c->op_bytes; |
| 1210 | c->dst.type = OP_REG; | 1212 | c->dst.type = OP_REG; |
| @@ -1214,7 +1216,10 @@ done_prefixes: | |||
| 1214 | } | 1216 | } |
| 1215 | c->dst.type = OP_MEM; | 1217 | c->dst.type = OP_MEM; |
| 1216 | c->dst.ptr = (unsigned long *)c->modrm_ea; | 1218 | c->dst.ptr = (unsigned long *)c->modrm_ea; |
| 1217 | c->dst.bytes = (c->d & ByteOp) ? 1 : c->op_bytes; | 1219 | if ((c->d & DstMask) == DstMem64) |
| 1220 | c->dst.bytes = 8; | ||
| 1221 | else | ||
| 1222 | c->dst.bytes = (c->d & ByteOp) ? 1 : c->op_bytes; | ||
| 1218 | c->dst.val = 0; | 1223 | c->dst.val = 0; |
| 1219 | if (c->d & BitOp) { | 1224 | if (c->d & BitOp) { |
| 1220 | unsigned long mask = ~(c->dst.bytes * 8 - 1); | 1225 | unsigned long mask = ~(c->dst.bytes * 8 - 1); |
| @@ -1706,12 +1711,7 @@ static inline int emulate_grp9(struct x86_emulate_ctxt *ctxt, | |||
| 1706 | struct x86_emulate_ops *ops) | 1711 | struct x86_emulate_ops *ops) |
| 1707 | { | 1712 | { |
| 1708 | struct decode_cache *c = &ctxt->decode; | 1713 | struct decode_cache *c = &ctxt->decode; |
| 1709 | u64 old, new; | 1714 | u64 old = c->dst.orig_val; |
| 1710 | int rc; | ||
| 1711 | |||
| 1712 | rc = ops->read_emulated(c->modrm_ea, &old, 8, ctxt->vcpu); | ||
| 1713 | if (rc != X86EMUL_CONTINUE) | ||
| 1714 | return rc; | ||
| 1715 | 1715 | ||
| 1716 | if (((u32) (old >> 0) != (u32) c->regs[VCPU_REGS_RAX]) || | 1716 | if (((u32) (old >> 0) != (u32) c->regs[VCPU_REGS_RAX]) || |
| 1717 | ((u32) (old >> 32) != (u32) c->regs[VCPU_REGS_RDX])) { | 1717 | ((u32) (old >> 32) != (u32) c->regs[VCPU_REGS_RDX])) { |
| @@ -1719,15 +1719,12 @@ static inline int emulate_grp9(struct x86_emulate_ctxt *ctxt, | |||
| 1719 | c->regs[VCPU_REGS_RAX] = (u32) (old >> 0); | 1719 | c->regs[VCPU_REGS_RAX] = (u32) (old >> 0); |
| 1720 | c->regs[VCPU_REGS_RDX] = (u32) (old >> 32); | 1720 | c->regs[VCPU_REGS_RDX] = (u32) (old >> 32); |
| 1721 | ctxt->eflags &= ~EFLG_ZF; | 1721 | ctxt->eflags &= ~EFLG_ZF; |
| 1722 | |||
| 1723 | } else { | 1722 | } else { |
| 1724 | new = ((u64)c->regs[VCPU_REGS_RCX] << 32) | | 1723 | c->dst.val = ((u64)c->regs[VCPU_REGS_RCX] << 32) | |
| 1725 | (u32) c->regs[VCPU_REGS_RBX]; | 1724 | (u32) c->regs[VCPU_REGS_RBX]; |
| 1726 | 1725 | ||
| 1727 | rc = ops->cmpxchg_emulated(c->modrm_ea, &old, &new, 8, ctxt->vcpu); | ||
| 1728 | if (rc != X86EMUL_CONTINUE) | ||
| 1729 | return rc; | ||
| 1730 | ctxt->eflags |= EFLG_ZF; | 1726 | ctxt->eflags |= EFLG_ZF; |
| 1727 | c->lock_prefix = 1; | ||
| 1731 | } | 1728 | } |
| 1732 | return X86EMUL_CONTINUE; | 1729 | return X86EMUL_CONTINUE; |
| 1733 | } | 1730 | } |
| @@ -3245,7 +3242,6 @@ twobyte_insn: | |||
| 3245 | rc = emulate_grp9(ctxt, ops); | 3242 | rc = emulate_grp9(ctxt, ops); |
| 3246 | if (rc != X86EMUL_CONTINUE) | 3243 | if (rc != X86EMUL_CONTINUE) |
| 3247 | goto done; | 3244 | goto done; |
| 3248 | c->dst.type = OP_NONE; | ||
| 3249 | break; | 3245 | break; |
| 3250 | } | 3246 | } |
| 3251 | goto writeback; | 3247 | goto writeback; |
