diff options
author | Gleb Natapov <gleb@redhat.com> | 2010-03-18 09:20:23 -0400 |
---|---|---|
committer | Avi Kivity <avi@redhat.com> | 2010-05-17 05:16:25 -0400 |
commit | cf8f70bfe38b326bb80b10f76d6544f571040229 (patch) | |
tree | d646456d773a887ca592d174b3d45a57d2779d85 /arch/x86/kvm/vmx.c | |
parent | d9271123a46011af26da680baeb7fdf67b498abf (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/vmx.c')
-rw-r--r-- | arch/x86/kvm/vmx.c | 18 |
1 files changed, 8 insertions, 10 deletions
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index 87b3c6843aac..1cceca1c59be 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c | |||
@@ -2985,22 +2985,20 @@ static int handle_io(struct kvm_vcpu *vcpu) | |||
2985 | int size, in, string; | 2985 | int size, in, string; |
2986 | unsigned port; | 2986 | unsigned port; |
2987 | 2987 | ||
2988 | ++vcpu->stat.io_exits; | ||
2989 | exit_qualification = vmcs_readl(EXIT_QUALIFICATION); | 2988 | exit_qualification = vmcs_readl(EXIT_QUALIFICATION); |
2990 | string = (exit_qualification & 16) != 0; | 2989 | string = (exit_qualification & 16) != 0; |
2990 | in = (exit_qualification & 8) != 0; | ||
2991 | 2991 | ||
2992 | if (string) { | 2992 | ++vcpu->stat.io_exits; |
2993 | if (emulate_instruction(vcpu, 0, 0, 0) == EMULATE_DO_MMIO) | ||
2994 | return 0; | ||
2995 | return 1; | ||
2996 | } | ||
2997 | 2993 | ||
2998 | size = (exit_qualification & 7) + 1; | 2994 | if (string || in) |
2999 | in = (exit_qualification & 8) != 0; | 2995 | return !(emulate_instruction(vcpu, 0, 0, 0) == EMULATE_DO_MMIO); |
3000 | port = exit_qualification >> 16; | ||
3001 | 2996 | ||
2997 | port = exit_qualification >> 16; | ||
2998 | size = (exit_qualification & 7) + 1; | ||
3002 | skip_emulated_instruction(vcpu); | 2999 | skip_emulated_instruction(vcpu); |
3003 | return kvm_emulate_pio(vcpu, in, size, port); | 3000 | |
3001 | return kvm_fast_pio_out(vcpu, size, port); | ||
3004 | } | 3002 | } |
3005 | 3003 | ||
3006 | static void | 3004 | static void |