aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/kvm
diff options
context:
space:
mode:
authorAvi Kivity <avi@qumranet.com>2007-01-05 19:36:51 -0500
committerLinus Torvalds <torvalds@woody.osdl.org>2007-01-06 02:55:26 -0500
commit32b35627355c3bf17e1903efd117efed7653a54e (patch)
tree9ef6ca5a32f6e224f4d463a89c21dda2ac08eafe /drivers/kvm
parent3bb65a22a4502067f8cd3cb4c923ffa70be62091 (diff)
[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>
Diffstat (limited to 'drivers/kvm')
-rw-r--r--drivers/kvm/kvm_main.c27
-rw-r--r--drivers/kvm/x86_emulate.c2
2 files changed, 28 insertions, 1 deletions
diff --git a/drivers/kvm/kvm_main.c b/drivers/kvm/kvm_main.c
index cec10106ce77..2e6bc5659953 100644
--- a/drivers/kvm/kvm_main.c
+++ b/drivers/kvm/kvm_main.c
@@ -936,6 +936,30 @@ static int emulator_cmpxchg_emulated(unsigned long addr,
936 return emulator_write_emulated(addr, new, bytes, ctxt); 936 return emulator_write_emulated(addr, new, bytes, ctxt);
937} 937}
938 938
939#ifdef CONFIG_X86_32
940
941static int emulator_cmpxchg8b_emulated(unsigned long addr,
942 unsigned long old_lo,
943 unsigned long old_hi,
944 unsigned long new_lo,
945 unsigned long new_hi,
946 struct x86_emulate_ctxt *ctxt)
947{
948 static int reported;
949 int r;
950
951 if (!reported) {
952 reported = 1;
953 printk(KERN_WARNING "kvm: emulating exchange8b as write\n");
954 }
955 r = emulator_write_emulated(addr, new_lo, 4, ctxt);
956 if (r != X86EMUL_CONTINUE)
957 return r;
958 return emulator_write_emulated(addr+4, new_hi, 4, ctxt);
959}
960
961#endif
962
939static unsigned long get_segment_base(struct kvm_vcpu *vcpu, int seg) 963static unsigned long get_segment_base(struct kvm_vcpu *vcpu, int seg)
940{ 964{
941 return kvm_arch_ops->get_segment_base(vcpu, seg); 965 return kvm_arch_ops->get_segment_base(vcpu, seg);
@@ -1010,6 +1034,9 @@ struct x86_emulate_ops emulate_ops = {
1010 .read_emulated = emulator_read_emulated, 1034 .read_emulated = emulator_read_emulated,
1011 .write_emulated = emulator_write_emulated, 1035 .write_emulated = emulator_write_emulated,
1012 .cmpxchg_emulated = emulator_cmpxchg_emulated, 1036 .cmpxchg_emulated = emulator_cmpxchg_emulated,
1037#ifdef CONFIG_X86_32
1038 .cmpxchg8b_emulated = emulator_cmpxchg8b_emulated,
1039#endif
1013}; 1040};
1014 1041
1015int emulate_instruction(struct kvm_vcpu *vcpu, 1042int emulate_instruction(struct kvm_vcpu *vcpu,
diff --git a/drivers/kvm/x86_emulate.c b/drivers/kvm/x86_emulate.c
index 1bff3e925fda..be70795b4822 100644
--- a/drivers/kvm/x86_emulate.c
+++ b/drivers/kvm/x86_emulate.c
@@ -1323,7 +1323,7 @@ twobyte_special_insn:
1323 ctxt)) != 0)) 1323 ctxt)) != 0))
1324 goto done; 1324 goto done;
1325 if ((old_lo != _regs[VCPU_REGS_RAX]) 1325 if ((old_lo != _regs[VCPU_REGS_RAX])
1326 || (old_hi != _regs[VCPU_REGS_RDI])) { 1326 || (old_hi != _regs[VCPU_REGS_RDX])) {
1327 _regs[VCPU_REGS_RAX] = old_lo; 1327 _regs[VCPU_REGS_RAX] = old_lo;
1328 _regs[VCPU_REGS_RDX] = old_hi; 1328 _regs[VCPU_REGS_RDX] = old_hi;
1329 _eflags &= ~EFLG_ZF; 1329 _eflags &= ~EFLG_ZF;