diff options
author | Jan Kiszka <jan.kiszka@siemens.com> | 2013-02-18 05:21:16 -0500 |
---|---|---|
committer | Marcelo Tosatti <mtosatti@redhat.com> | 2013-02-21 22:50:42 -0500 |
commit | 908a7bdd6adba3dfd35d8a74a48aed90593de178 (patch) | |
tree | f4f5aa9cdbed2d55c49525b431a88d0ad047157e /arch/x86/kvm/vmx.c | |
parent | 6b73a96065e89dc9fa75ba4f78b1aa3a3bbd0470 (diff) |
KVM: nVMX: Improve I/O exit handling
This prevents trapping L2 I/O exits if L1 has neither unconditional nor
bitmap-based exiting enabled. Furthermore, it implements I/O bitmap
handling.
Reviewed-by: Gleb Natapov <gleb@redhat.com>
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.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 | 49 |
1 files changed, 47 insertions, 2 deletions
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index 6667042714cc..b4ce43c82748 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c | |||
@@ -5908,6 +5908,52 @@ static int (*const kvm_vmx_exit_handlers[])(struct kvm_vcpu *vcpu) = { | |||
5908 | static const int kvm_vmx_max_exit_handlers = | 5908 | static const int kvm_vmx_max_exit_handlers = |
5909 | ARRAY_SIZE(kvm_vmx_exit_handlers); | 5909 | ARRAY_SIZE(kvm_vmx_exit_handlers); |
5910 | 5910 | ||
5911 | static bool nested_vmx_exit_handled_io(struct kvm_vcpu *vcpu, | ||
5912 | struct vmcs12 *vmcs12) | ||
5913 | { | ||
5914 | unsigned long exit_qualification; | ||
5915 | gpa_t bitmap, last_bitmap; | ||
5916 | unsigned int port; | ||
5917 | int size; | ||
5918 | u8 b; | ||
5919 | |||
5920 | if (nested_cpu_has(vmcs12, CPU_BASED_UNCOND_IO_EXITING)) | ||
5921 | return 1; | ||
5922 | |||
5923 | if (!nested_cpu_has(vmcs12, CPU_BASED_USE_IO_BITMAPS)) | ||
5924 | return 0; | ||
5925 | |||
5926 | exit_qualification = vmcs_readl(EXIT_QUALIFICATION); | ||
5927 | |||
5928 | port = exit_qualification >> 16; | ||
5929 | size = (exit_qualification & 7) + 1; | ||
5930 | |||
5931 | last_bitmap = (gpa_t)-1; | ||
5932 | b = -1; | ||
5933 | |||
5934 | while (size > 0) { | ||
5935 | if (port < 0x8000) | ||
5936 | bitmap = vmcs12->io_bitmap_a; | ||
5937 | else if (port < 0x10000) | ||
5938 | bitmap = vmcs12->io_bitmap_b; | ||
5939 | else | ||
5940 | return 1; | ||
5941 | bitmap += (port & 0x7fff) / 8; | ||
5942 | |||
5943 | if (last_bitmap != bitmap) | ||
5944 | if (kvm_read_guest(vcpu->kvm, bitmap, &b, 1)) | ||
5945 | return 1; | ||
5946 | if (b & (1 << (port & 7))) | ||
5947 | return 1; | ||
5948 | |||
5949 | port++; | ||
5950 | size--; | ||
5951 | last_bitmap = bitmap; | ||
5952 | } | ||
5953 | |||
5954 | return 0; | ||
5955 | } | ||
5956 | |||
5911 | /* | 5957 | /* |
5912 | * Return 1 if we should exit from L2 to L1 to handle an MSR access access, | 5958 | * Return 1 if we should exit from L2 to L1 to handle an MSR access access, |
5913 | * rather than handle it ourselves in L0. I.e., check whether L1 expressed | 5959 | * rather than handle it ourselves in L0. I.e., check whether L1 expressed |
@@ -6097,8 +6143,7 @@ static bool nested_vmx_exit_handled(struct kvm_vcpu *vcpu) | |||
6097 | case EXIT_REASON_DR_ACCESS: | 6143 | case EXIT_REASON_DR_ACCESS: |
6098 | return nested_cpu_has(vmcs12, CPU_BASED_MOV_DR_EXITING); | 6144 | return nested_cpu_has(vmcs12, CPU_BASED_MOV_DR_EXITING); |
6099 | case EXIT_REASON_IO_INSTRUCTION: | 6145 | case EXIT_REASON_IO_INSTRUCTION: |
6100 | /* TODO: support IO bitmaps */ | 6146 | return nested_vmx_exit_handled_io(vcpu, vmcs12); |
6101 | return 1; | ||
6102 | case EXIT_REASON_MSR_READ: | 6147 | case EXIT_REASON_MSR_READ: |
6103 | case EXIT_REASON_MSR_WRITE: | 6148 | case EXIT_REASON_MSR_WRITE: |
6104 | return nested_vmx_exit_handled_msr(vcpu, vmcs12, exit_reason); | 6149 | return nested_vmx_exit_handled_msr(vcpu, vmcs12, exit_reason); |