aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWanpeng Li <wanpeng.li@linux.intel.com>2014-08-21 07:46:50 -0400
committerPaolo Bonzini <pbonzini@redhat.com>2014-08-29 08:02:48 -0400
commita7c0b07d570848e50fce4d31ac01313484d6b844 (patch)
tree2a63548b81b2c1d6bdfbe3c68b8b4c3989d5e700
parenta2bcba5035bb3d7fb3099e1893026316365f4b5d (diff)
KVM: nVMX: nested TPR shadow/threshold emulation
This patch fix bug https://bugzilla.kernel.org/show_bug.cgi?id=61411 TPR shadow/threshold feature is important to speed up the Windows guest. Besides, it is a must feature for certain VMM. We map virtual APIC page address and TPR threshold from L1 VMCS. If TPR_BELOW_THRESHOLD VM exit is triggered by L2 guest and L1 interested in, we inject it into L1 VMM for handling. Reviewed-by: Paolo Bonzini <pbonzini@redhat.com> Signed-off-by: Wanpeng Li <wanpeng.li@linux.intel.com> [Add PAGE_ALIGNED check, do not write useless virtual APIC page address if TPR shadowing is disabled. - Paolo] Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
-rw-r--r--arch/x86/kvm/vmx.c54
1 files changed, 51 insertions, 3 deletions
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index 70516e11f051..73ba2a265f85 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -397,6 +397,7 @@ struct nested_vmx {
397 * we must keep them pinned while L2 runs. 397 * we must keep them pinned while L2 runs.
398 */ 398 */
399 struct page *apic_access_page; 399 struct page *apic_access_page;
400 struct page *virtual_apic_page;
400 u64 msr_ia32_feature_control; 401 u64 msr_ia32_feature_control;
401 402
402 struct hrtimer preemption_timer; 403 struct hrtimer preemption_timer;
@@ -555,6 +556,7 @@ static int max_shadow_read_only_fields =
555 ARRAY_SIZE(shadow_read_only_fields); 556 ARRAY_SIZE(shadow_read_only_fields);
556 557
557static unsigned long shadow_read_write_fields[] = { 558static unsigned long shadow_read_write_fields[] = {
559 TPR_THRESHOLD,
558 GUEST_RIP, 560 GUEST_RIP,
559 GUEST_RSP, 561 GUEST_RSP,
560 GUEST_CR0, 562 GUEST_CR0,
@@ -2352,7 +2354,7 @@ static __init void nested_vmx_setup_ctls_msrs(void)
2352 CPU_BASED_MOV_DR_EXITING | CPU_BASED_UNCOND_IO_EXITING | 2354 CPU_BASED_MOV_DR_EXITING | CPU_BASED_UNCOND_IO_EXITING |
2353 CPU_BASED_USE_IO_BITMAPS | CPU_BASED_MONITOR_EXITING | 2355 CPU_BASED_USE_IO_BITMAPS | CPU_BASED_MONITOR_EXITING |
2354 CPU_BASED_RDPMC_EXITING | CPU_BASED_RDTSC_EXITING | 2356 CPU_BASED_RDPMC_EXITING | CPU_BASED_RDTSC_EXITING |
2355 CPU_BASED_PAUSE_EXITING | 2357 CPU_BASED_PAUSE_EXITING | CPU_BASED_TPR_SHADOW |
2356 CPU_BASED_ACTIVATE_SECONDARY_CONTROLS; 2358 CPU_BASED_ACTIVATE_SECONDARY_CONTROLS;
2357 /* 2359 /*
2358 * We can allow some features even when not supported by the 2360 * We can allow some features even when not supported by the
@@ -6246,6 +6248,10 @@ static void free_nested(struct vcpu_vmx *vmx)
6246 nested_release_page(vmx->nested.apic_access_page); 6248 nested_release_page(vmx->nested.apic_access_page);
6247 vmx->nested.apic_access_page = 0; 6249 vmx->nested.apic_access_page = 0;
6248 } 6250 }
6251 if (vmx->nested.virtual_apic_page) {
6252 nested_release_page(vmx->nested.virtual_apic_page);
6253 vmx->nested.virtual_apic_page = 0;
6254 }
6249 6255
6250 nested_free_all_saved_vmcss(vmx); 6256 nested_free_all_saved_vmcss(vmx);
6251} 6257}
@@ -7034,7 +7040,7 @@ static bool nested_vmx_exit_handled(struct kvm_vcpu *vcpu)
7034 case EXIT_REASON_MCE_DURING_VMENTRY: 7040 case EXIT_REASON_MCE_DURING_VMENTRY:
7035 return 0; 7041 return 0;
7036 case EXIT_REASON_TPR_BELOW_THRESHOLD: 7042 case EXIT_REASON_TPR_BELOW_THRESHOLD:
7037 return 1; 7043 return nested_cpu_has(vmcs12, CPU_BASED_TPR_SHADOW);
7038 case EXIT_REASON_APIC_ACCESS: 7044 case EXIT_REASON_APIC_ACCESS:
7039 return nested_cpu_has2(vmcs12, 7045 return nested_cpu_has2(vmcs12,
7040 SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES); 7046 SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES);
@@ -7155,6 +7161,12 @@ static int vmx_handle_exit(struct kvm_vcpu *vcpu)
7155 7161
7156static void update_cr8_intercept(struct kvm_vcpu *vcpu, int tpr, int irr) 7162static void update_cr8_intercept(struct kvm_vcpu *vcpu, int tpr, int irr)
7157{ 7163{
7164 struct vmcs12 *vmcs12 = get_vmcs12(vcpu);
7165
7166 if (is_guest_mode(vcpu) &&
7167 nested_cpu_has(vmcs12, CPU_BASED_TPR_SHADOW))
7168 return;
7169
7158 if (irr == -1 || tpr < irr) { 7170 if (irr == -1 || tpr < irr) {
7159 vmcs_write32(TPR_THRESHOLD, 0); 7171 vmcs_write32(TPR_THRESHOLD, 0);
7160 return; 7172 return;
@@ -7933,8 +7945,8 @@ static bool nested_get_vmcs12_pages(struct kvm_vcpu *vcpu,
7933 struct vcpu_vmx *vmx = to_vmx(vcpu); 7945 struct vcpu_vmx *vmx = to_vmx(vcpu);
7934 7946
7935 if (nested_cpu_has2(vmcs12, SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES)) { 7947 if (nested_cpu_has2(vmcs12, SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES)) {
7948 /* TODO: Also verify bits beyond physical address width are 0 */
7936 if (!PAGE_ALIGNED(vmcs12->apic_access_addr)) 7949 if (!PAGE_ALIGNED(vmcs12->apic_access_addr))
7937 /*TODO: Also verify bits beyond physical address width are 0*/
7938 return false; 7950 return false;
7939 7951
7940 /* 7952 /*
@@ -7948,6 +7960,31 @@ static bool nested_get_vmcs12_pages(struct kvm_vcpu *vcpu,
7948 vmx->nested.apic_access_page = 7960 vmx->nested.apic_access_page =
7949 nested_get_page(vcpu, vmcs12->apic_access_addr); 7961 nested_get_page(vcpu, vmcs12->apic_access_addr);
7950 } 7962 }
7963
7964 if (nested_cpu_has(vmcs12, CPU_BASED_TPR_SHADOW)) {
7965 /* TODO: Also verify bits beyond physical address width are 0 */
7966 if (!PAGE_ALIGNED(vmcs12->virtual_apic_page_addr))
7967 return false;
7968
7969 if (vmx->nested.virtual_apic_page) /* shouldn't happen */
7970 nested_release_page(vmx->nested.virtual_apic_page);
7971 vmx->nested.virtual_apic_page =
7972 nested_get_page(vcpu, vmcs12->virtual_apic_page_addr);
7973
7974 /*
7975 * Failing the vm entry is _not_ what the processor does
7976 * but it's basically the only possibility we have.
7977 * We could still enter the guest if CR8 load exits are
7978 * enabled, CR8 store exits are enabled, and virtualize APIC
7979 * access is disabled; in this case the processor would never
7980 * use the TPR shadow and we could simply clear the bit from
7981 * the execution control. But such a configuration is useless,
7982 * so let's keep the code simple.
7983 */
7984 if (!vmx->nested.virtual_apic_page)
7985 return false;
7986 }
7987
7951 return true; 7988 return true;
7952} 7989}
7953 7990
@@ -8141,6 +8178,13 @@ static void prepare_vmcs02(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12)
8141 exec_control &= ~CPU_BASED_VIRTUAL_NMI_PENDING; 8178 exec_control &= ~CPU_BASED_VIRTUAL_NMI_PENDING;
8142 exec_control &= ~CPU_BASED_TPR_SHADOW; 8179 exec_control &= ~CPU_BASED_TPR_SHADOW;
8143 exec_control |= vmcs12->cpu_based_vm_exec_control; 8180 exec_control |= vmcs12->cpu_based_vm_exec_control;
8181
8182 if (exec_control & CPU_BASED_TPR_SHADOW) {
8183 vmcs_write64(VIRTUAL_APIC_PAGE_ADDR,
8184 page_to_phys(vmx->nested.virtual_apic_page));
8185 vmcs_write32(TPR_THRESHOLD, vmcs12->tpr_threshold);
8186 }
8187
8144 /* 8188 /*
8145 * Merging of IO and MSR bitmaps not currently supported. 8189 * Merging of IO and MSR bitmaps not currently supported.
8146 * Rather, exit every time. 8190 * Rather, exit every time.
@@ -8908,6 +8952,10 @@ static void nested_vmx_vmexit(struct kvm_vcpu *vcpu, u32 exit_reason,
8908 nested_release_page(vmx->nested.apic_access_page); 8952 nested_release_page(vmx->nested.apic_access_page);
8909 vmx->nested.apic_access_page = 0; 8953 vmx->nested.apic_access_page = 0;
8910 } 8954 }
8955 if (vmx->nested.virtual_apic_page) {
8956 nested_release_page(vmx->nested.virtual_apic_page);
8957 vmx->nested.virtual_apic_page = 0;
8958 }
8911 8959
8912 /* 8960 /*
8913 * Exiting from L2 to L1, we're now back to L1 which thinks it just 8961 * Exiting from L2 to L1, we're now back to L1 which thinks it just