aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kvm/vmx.c
diff options
context:
space:
mode:
authorJan Kiszka <jan.kiszka@siemens.com>2013-02-18 05:21:16 -0500
committerMarcelo Tosatti <mtosatti@redhat.com>2013-02-21 22:50:42 -0500
commit908a7bdd6adba3dfd35d8a74a48aed90593de178 (patch)
treef4f5aa9cdbed2d55c49525b431a88d0ad047157e /arch/x86/kvm/vmx.c
parent6b73a96065e89dc9fa75ba4f78b1aa3a3bbd0470 (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.c49
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) = {
5908static const int kvm_vmx_max_exit_handlers = 5908static const int kvm_vmx_max_exit_handlers =
5909 ARRAY_SIZE(kvm_vmx_exit_handlers); 5909 ARRAY_SIZE(kvm_vmx_exit_handlers);
5910 5910
5911static 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);