diff options
author | Avi Kivity <avi@redhat.com> | 2010-08-26 07:31:30 -0400 |
---|---|---|
committer | Marcelo Tosatti <mtosatti@redhat.com> | 2010-09-08 13:50:55 -0400 |
commit | 16518d5ada690643453eb0aef3cc7841d3623c2d (patch) | |
tree | 1ecef3f87959e48d34f2815ddd66b49da1adfa3d /arch/x86 | |
parent | d56557af19867edb8c0e96f8e26399698a08857f (diff) |
KVM: x86 emulator: fix regression with cmpxchg8b on i386 hosts
operand::val and operand::orig_val are 32-bit on i386, whereas cmpxchg8b
operands are 64-bit.
Fix by adding val64 and orig_val64 union members to struct operand, and
using them where needed.
Signed-off-by: Avi Kivity <avi@redhat.com>
Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
Diffstat (limited to 'arch/x86')
-rw-r--r-- | arch/x86/include/asm/kvm_emulate.h | 7 | ||||
-rw-r--r-- | arch/x86/kvm/emulate.c | 9 |
2 files changed, 10 insertions, 6 deletions
diff --git a/arch/x86/include/asm/kvm_emulate.h b/arch/x86/include/asm/kvm_emulate.h index 51cfd730ac5d..1f99ecfc48e1 100644 --- a/arch/x86/include/asm/kvm_emulate.h +++ b/arch/x86/include/asm/kvm_emulate.h | |||
@@ -152,9 +152,14 @@ struct x86_emulate_ops { | |||
152 | struct operand { | 152 | struct operand { |
153 | enum { OP_REG, OP_MEM, OP_IMM, OP_NONE } type; | 153 | enum { OP_REG, OP_MEM, OP_IMM, OP_NONE } type; |
154 | unsigned int bytes; | 154 | unsigned int bytes; |
155 | unsigned long orig_val, *ptr; | 155 | union { |
156 | unsigned long orig_val; | ||
157 | u64 orig_val64; | ||
158 | }; | ||
159 | unsigned long *ptr; | ||
156 | union { | 160 | union { |
157 | unsigned long val; | 161 | unsigned long val; |
162 | u64 val64; | ||
158 | char valptr[sizeof(unsigned long) + 2]; | 163 | char valptr[sizeof(unsigned long) + 2]; |
159 | }; | 164 | }; |
160 | }; | 165 | }; |
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c index b38bd8b92aa6..66ca98aafdd6 100644 --- a/arch/x86/kvm/emulate.c +++ b/arch/x86/kvm/emulate.c | |||
@@ -1870,17 +1870,16 @@ static inline int emulate_grp9(struct x86_emulate_ctxt *ctxt, | |||
1870 | struct x86_emulate_ops *ops) | 1870 | struct x86_emulate_ops *ops) |
1871 | { | 1871 | { |
1872 | struct decode_cache *c = &ctxt->decode; | 1872 | struct decode_cache *c = &ctxt->decode; |
1873 | u64 old = c->dst.orig_val; | 1873 | u64 old = c->dst.orig_val64; |
1874 | 1874 | ||
1875 | if (((u32) (old >> 0) != (u32) c->regs[VCPU_REGS_RAX]) || | 1875 | if (((u32) (old >> 0) != (u32) c->regs[VCPU_REGS_RAX]) || |
1876 | ((u32) (old >> 32) != (u32) c->regs[VCPU_REGS_RDX])) { | 1876 | ((u32) (old >> 32) != (u32) c->regs[VCPU_REGS_RDX])) { |
1877 | |||
1878 | c->regs[VCPU_REGS_RAX] = (u32) (old >> 0); | 1877 | c->regs[VCPU_REGS_RAX] = (u32) (old >> 0); |
1879 | c->regs[VCPU_REGS_RDX] = (u32) (old >> 32); | 1878 | c->regs[VCPU_REGS_RDX] = (u32) (old >> 32); |
1880 | ctxt->eflags &= ~EFLG_ZF; | 1879 | ctxt->eflags &= ~EFLG_ZF; |
1881 | } else { | 1880 | } else { |
1882 | c->dst.val = ((u64)c->regs[VCPU_REGS_RCX] << 32) | | 1881 | c->dst.val64 = ((u64)c->regs[VCPU_REGS_RCX] << 32) | |
1883 | (u32) c->regs[VCPU_REGS_RBX]; | 1882 | (u32) c->regs[VCPU_REGS_RBX]; |
1884 | 1883 | ||
1885 | ctxt->eflags |= EFLG_ZF; | 1884 | ctxt->eflags |= EFLG_ZF; |
1886 | } | 1885 | } |
@@ -2616,7 +2615,7 @@ x86_emulate_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops) | |||
2616 | c->src.valptr, c->src.bytes); | 2615 | c->src.valptr, c->src.bytes); |
2617 | if (rc != X86EMUL_CONTINUE) | 2616 | if (rc != X86EMUL_CONTINUE) |
2618 | goto done; | 2617 | goto done; |
2619 | c->src.orig_val = c->src.val; | 2618 | c->src.orig_val64 = c->src.val64; |
2620 | } | 2619 | } |
2621 | 2620 | ||
2622 | if (c->src2.type == OP_MEM) { | 2621 | if (c->src2.type == OP_MEM) { |