[PATCH] KVM: MMU: Fix cmpxchg8b emulation
cmpxchg8b uses edx:eax as the compare operand, not edi:eax. cmpxchg8b is used by 32-bit pae guests to set page table entries atomically, and this is emulated touching shadowed guest page tables. Also, implement it for 32-bit hosts. Signed-off-by: Avi Kivity <avi@qumranet.com> Acked-by: Ingo Molnar <mingo@elte.hu> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
This commit is contained in:
committed by
Linus Torvalds
parent
3bb65a22a4
commit
32b3562735
@@ -936,6 +936,30 @@ static int emulator_cmpxchg_emulated(unsigned long addr,
|
|||||||
return emulator_write_emulated(addr, new, bytes, ctxt);
|
return emulator_write_emulated(addr, new, bytes, ctxt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_X86_32
|
||||||
|
|
||||||
|
static int emulator_cmpxchg8b_emulated(unsigned long addr,
|
||||||
|
unsigned long old_lo,
|
||||||
|
unsigned long old_hi,
|
||||||
|
unsigned long new_lo,
|
||||||
|
unsigned long new_hi,
|
||||||
|
struct x86_emulate_ctxt *ctxt)
|
||||||
|
{
|
||||||
|
static int reported;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
if (!reported) {
|
||||||
|
reported = 1;
|
||||||
|
printk(KERN_WARNING "kvm: emulating exchange8b as write\n");
|
||||||
|
}
|
||||||
|
r = emulator_write_emulated(addr, new_lo, 4, ctxt);
|
||||||
|
if (r != X86EMUL_CONTINUE)
|
||||||
|
return r;
|
||||||
|
return emulator_write_emulated(addr+4, new_hi, 4, ctxt);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
static unsigned long get_segment_base(struct kvm_vcpu *vcpu, int seg)
|
static unsigned long get_segment_base(struct kvm_vcpu *vcpu, int seg)
|
||||||
{
|
{
|
||||||
return kvm_arch_ops->get_segment_base(vcpu, seg);
|
return kvm_arch_ops->get_segment_base(vcpu, seg);
|
||||||
@@ -1010,6 +1034,9 @@ struct x86_emulate_ops emulate_ops = {
|
|||||||
.read_emulated = emulator_read_emulated,
|
.read_emulated = emulator_read_emulated,
|
||||||
.write_emulated = emulator_write_emulated,
|
.write_emulated = emulator_write_emulated,
|
||||||
.cmpxchg_emulated = emulator_cmpxchg_emulated,
|
.cmpxchg_emulated = emulator_cmpxchg_emulated,
|
||||||
|
#ifdef CONFIG_X86_32
|
||||||
|
.cmpxchg8b_emulated = emulator_cmpxchg8b_emulated,
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
int emulate_instruction(struct kvm_vcpu *vcpu,
|
int emulate_instruction(struct kvm_vcpu *vcpu,
|
||||||
|
@@ -1323,7 +1323,7 @@ twobyte_special_insn:
|
|||||||
ctxt)) != 0))
|
ctxt)) != 0))
|
||||||
goto done;
|
goto done;
|
||||||
if ((old_lo != _regs[VCPU_REGS_RAX])
|
if ((old_lo != _regs[VCPU_REGS_RAX])
|
||||||
|| (old_hi != _regs[VCPU_REGS_RDI])) {
|
|| (old_hi != _regs[VCPU_REGS_RDX])) {
|
||||||
_regs[VCPU_REGS_RAX] = old_lo;
|
_regs[VCPU_REGS_RAX] = old_lo;
|
||||||
_regs[VCPU_REGS_RDX] = old_hi;
|
_regs[VCPU_REGS_RDX] = old_hi;
|
||||||
_eflags &= ~EFLG_ZF;
|
_eflags &= ~EFLG_ZF;
|
||||||
|
Reference in New Issue
Block a user