aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kvm/svm.c
diff options
context:
space:
mode:
authorGleb Natapov <gleb@redhat.com>2010-03-18 09:20:23 -0400
committerAvi Kivity <avi@redhat.com>2010-05-17 05:16:25 -0400
commitcf8f70bfe38b326bb80b10f76d6544f571040229 (patch)
treed646456d773a887ca592d174b3d45a57d2779d85 /arch/x86/kvm/svm.c
parentd9271123a46011af26da680baeb7fdf67b498abf (diff)
KVM: x86 emulator: fix in/out emulation.
in/out emulation is broken now. The breakage is different depending on where IO device resides. If it is in userspace emulator reports emulation failure since it incorrectly interprets kvm_emulate_pio() return value. If IO device is in the kernel emulation of 'in' will do nothing since kvm_emulate_pio() stores result directly into vcpu registers, so emulator will overwrite result of emulation during commit of shadowed register. Signed-off-by: Gleb Natapov <gleb@redhat.com> Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
Diffstat (limited to 'arch/x86/kvm/svm.c')
-rw-r--r--arch/x86/kvm/svm.c20
1 files changed, 7 insertions, 13 deletions
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
index abbc3f9d03b2..e9f79619e185 100644
--- a/arch/x86/kvm/svm.c
+++ b/arch/x86/kvm/svm.c
@@ -1494,29 +1494,23 @@ static int shutdown_interception(struct vcpu_svm *svm)
1494 1494
1495static int io_interception(struct vcpu_svm *svm) 1495static int io_interception(struct vcpu_svm *svm)
1496{ 1496{
1497 struct kvm_vcpu *vcpu = &svm->vcpu;
1497 u32 io_info = svm->vmcb->control.exit_info_1; /* address size bug? */ 1498 u32 io_info = svm->vmcb->control.exit_info_1; /* address size bug? */
1498 int size, in, string; 1499 int size, in, string;
1499 unsigned port; 1500 unsigned port;
1500 1501
1501 ++svm->vcpu.stat.io_exits; 1502 ++svm->vcpu.stat.io_exits;
1502
1503 svm->next_rip = svm->vmcb->control.exit_info_2;
1504
1505 string = (io_info & SVM_IOIO_STR_MASK) != 0; 1503 string = (io_info & SVM_IOIO_STR_MASK) != 0;
1506
1507 if (string) {
1508 if (emulate_instruction(&svm->vcpu,
1509 0, 0, 0) == EMULATE_DO_MMIO)
1510 return 0;
1511 return 1;
1512 }
1513
1514 in = (io_info & SVM_IOIO_TYPE_MASK) != 0; 1504 in = (io_info & SVM_IOIO_TYPE_MASK) != 0;
1505 if (string || in)
1506 return !(emulate_instruction(vcpu, 0, 0, 0) == EMULATE_DO_MMIO);
1507
1515 port = io_info >> 16; 1508 port = io_info >> 16;
1516 size = (io_info & SVM_IOIO_SIZE_MASK) >> SVM_IOIO_SIZE_SHIFT; 1509 size = (io_info & SVM_IOIO_SIZE_MASK) >> SVM_IOIO_SIZE_SHIFT;
1517 1510 svm->next_rip = svm->vmcb->control.exit_info_2;
1518 skip_emulated_instruction(&svm->vcpu); 1511 skip_emulated_instruction(&svm->vcpu);
1519 return kvm_emulate_pio(&svm->vcpu, in, size, port); 1512
1513 return kvm_fast_pio_out(vcpu, size, port);
1520} 1514}
1521 1515
1522static int nmi_interception(struct vcpu_svm *svm) 1516static int nmi_interception(struct vcpu_svm *svm)