aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaolo Bonzini <pbonzini@redhat.com>2017-08-24 07:55:35 -0400
committerPaolo Bonzini <pbonzini@redhat.com>2017-08-24 09:35:14 -0400
commit80154d77c922d0f9bb1e4d115ff760c066c12d8f (patch)
tree44a3b127ce9e25c58528bd44990ca9624260667c
parent640bd6e5752274f7dbd2a0a6642fe2db85813bd9 (diff)
KVM: VMX: cache secondary exec controls
Currently, secondary execution controls are divided in three groups: - static, depending mostly on the module arguments or the processor (vmx_secondary_exec_control) - static, depending on CPUID (vmx_cpuid_update) - dynamic, depending on nested VMX or local APIC state Because walking CPUID is expensive, prepare_vmcs02 is using only the first group. This however is unnecessarily complicated. Just cache the static secondary execution controls, and then prepare_vmcs02 does not need to compute them every time. Computation of all static secondary execution controls is now kept in a single function, vmx_compute_secondary_exec_control. Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
-rw-r--r--arch/x86/kvm/vmx.c100
1 files changed, 54 insertions, 46 deletions
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index 19aa69af7c2d..08381a5d8879 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -576,6 +576,8 @@ struct vcpu_vmx {
576#endif 576#endif
577 u32 vm_entry_controls_shadow; 577 u32 vm_entry_controls_shadow;
578 u32 vm_exit_controls_shadow; 578 u32 vm_exit_controls_shadow;
579 u32 secondary_exec_control;
580
579 /* 581 /*
580 * loaded_vmcs points to the VMCS currently used in this vcpu. For a 582 * loaded_vmcs points to the VMCS currently used in this vcpu. For a
581 * non-nested (L1) guest, it always points to vmcs01. For a nested 583 * non-nested (L1) guest, it always points to vmcs01. For a nested
@@ -2807,7 +2809,10 @@ static void nested_vmx_setup_ctls_msrs(struct vcpu_vmx *vmx)
2807 vmx->nested.nested_vmx_procbased_ctls_low &= 2809 vmx->nested.nested_vmx_procbased_ctls_low &=
2808 ~(CPU_BASED_CR3_LOAD_EXITING | CPU_BASED_CR3_STORE_EXITING); 2810 ~(CPU_BASED_CR3_LOAD_EXITING | CPU_BASED_CR3_STORE_EXITING);
2809 2811
2810 /* secondary cpu-based controls */ 2812 /*
2813 * secondary cpu-based controls. Do not include those that
2814 * depend on CPUID bits, they are added later by vmx_cpuid_update.
2815 */
2811 rdmsr(MSR_IA32_VMX_PROCBASED_CTLS2, 2816 rdmsr(MSR_IA32_VMX_PROCBASED_CTLS2,
2812 vmx->nested.nested_vmx_secondary_ctls_low, 2817 vmx->nested.nested_vmx_secondary_ctls_low,
2813 vmx->nested.nested_vmx_secondary_ctls_high); 2818 vmx->nested.nested_vmx_secondary_ctls_high);
@@ -2815,7 +2820,6 @@ static void nested_vmx_setup_ctls_msrs(struct vcpu_vmx *vmx)
2815 vmx->nested.nested_vmx_secondary_ctls_high &= 2820 vmx->nested.nested_vmx_secondary_ctls_high &=
2816 SECONDARY_EXEC_RDRAND | SECONDARY_EXEC_RDSEED | 2821 SECONDARY_EXEC_RDRAND | SECONDARY_EXEC_RDSEED |
2817 SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES | 2822 SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES |
2818 SECONDARY_EXEC_RDTSCP |
2819 SECONDARY_EXEC_DESC | 2823 SECONDARY_EXEC_DESC |
2820 SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE | 2824 SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE |
2821 SECONDARY_EXEC_APIC_REGISTER_VIRT | 2825 SECONDARY_EXEC_APIC_REGISTER_VIRT |
@@ -5269,10 +5273,12 @@ static u32 vmx_exec_control(struct vcpu_vmx *vmx)
5269 return exec_control; 5273 return exec_control;
5270} 5274}
5271 5275
5272static u32 vmx_secondary_exec_control(struct vcpu_vmx *vmx) 5276static void vmx_compute_secondary_exec_control(struct vcpu_vmx *vmx)
5273{ 5277{
5278 struct kvm_vcpu *vcpu = &vmx->vcpu;
5279
5274 u32 exec_control = vmcs_config.cpu_based_2nd_exec_ctrl; 5280 u32 exec_control = vmcs_config.cpu_based_2nd_exec_ctrl;
5275 if (!cpu_need_virtualize_apic_accesses(&vmx->vcpu)) 5281 if (!cpu_need_virtualize_apic_accesses(vcpu))
5276 exec_control &= ~SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES; 5282 exec_control &= ~SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES;
5277 if (vmx->vpid == 0) 5283 if (vmx->vpid == 0)
5278 exec_control &= ~SECONDARY_EXEC_ENABLE_VPID; 5284 exec_control &= ~SECONDARY_EXEC_ENABLE_VPID;
@@ -5286,7 +5292,7 @@ static u32 vmx_secondary_exec_control(struct vcpu_vmx *vmx)
5286 exec_control &= ~SECONDARY_EXEC_UNRESTRICTED_GUEST; 5292 exec_control &= ~SECONDARY_EXEC_UNRESTRICTED_GUEST;
5287 if (!ple_gap) 5293 if (!ple_gap)
5288 exec_control &= ~SECONDARY_EXEC_PAUSE_LOOP_EXITING; 5294 exec_control &= ~SECONDARY_EXEC_PAUSE_LOOP_EXITING;
5289 if (!kvm_vcpu_apicv_active(&vmx->vcpu)) 5295 if (!kvm_vcpu_apicv_active(vcpu))
5290 exec_control &= ~(SECONDARY_EXEC_APIC_REGISTER_VIRT | 5296 exec_control &= ~(SECONDARY_EXEC_APIC_REGISTER_VIRT |
5291 SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY); 5297 SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY);
5292 exec_control &= ~SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE; 5298 exec_control &= ~SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE;
@@ -5300,7 +5306,43 @@ static u32 vmx_secondary_exec_control(struct vcpu_vmx *vmx)
5300 if (!enable_pml) 5306 if (!enable_pml)
5301 exec_control &= ~SECONDARY_EXEC_ENABLE_PML; 5307 exec_control &= ~SECONDARY_EXEC_ENABLE_PML;
5302 5308
5303 return exec_control; 5309 if (vmx_rdtscp_supported()) {
5310 bool rdtscp_enabled = guest_cpuid_has(vcpu, X86_FEATURE_RDTSCP);
5311 if (!rdtscp_enabled)
5312 exec_control &= ~SECONDARY_EXEC_RDTSCP;
5313
5314 if (nested) {
5315 if (rdtscp_enabled)
5316 vmx->nested.nested_vmx_secondary_ctls_high |=
5317 SECONDARY_EXEC_RDTSCP;
5318 else
5319 vmx->nested.nested_vmx_secondary_ctls_high &=
5320 ~SECONDARY_EXEC_RDTSCP;
5321 }
5322 }
5323
5324 if (vmx_invpcid_supported()) {
5325 /* Exposing INVPCID only when PCID is exposed */
5326 bool invpcid_enabled =
5327 guest_cpuid_has(vcpu, X86_FEATURE_INVPCID) &&
5328 guest_cpuid_has(vcpu, X86_FEATURE_PCID);
5329
5330 if (!invpcid_enabled) {
5331 exec_control &= ~SECONDARY_EXEC_ENABLE_INVPCID;
5332 guest_cpuid_clear(vcpu, X86_FEATURE_INVPCID);
5333 }
5334
5335 if (nested) {
5336 if (invpcid_enabled)
5337 vmx->nested.nested_vmx_secondary_ctls_high |=
5338 SECONDARY_EXEC_ENABLE_INVPCID;
5339 else
5340 vmx->nested.nested_vmx_secondary_ctls_high &=
5341 ~SECONDARY_EXEC_ENABLE_INVPCID;
5342 }
5343 }
5344
5345 vmx->secondary_exec_control = exec_control;
5304} 5346}
5305 5347
5306static void ept_set_mmio_spte_mask(void) 5348static void ept_set_mmio_spte_mask(void)
@@ -5344,8 +5386,9 @@ static int vmx_vcpu_setup(struct vcpu_vmx *vmx)
5344 vmcs_write32(CPU_BASED_VM_EXEC_CONTROL, vmx_exec_control(vmx)); 5386 vmcs_write32(CPU_BASED_VM_EXEC_CONTROL, vmx_exec_control(vmx));
5345 5387
5346 if (cpu_has_secondary_exec_ctrls()) { 5388 if (cpu_has_secondary_exec_ctrls()) {
5389 vmx_compute_secondary_exec_control(vmx);
5347 vmcs_write32(SECONDARY_VM_EXEC_CONTROL, 5390 vmcs_write32(SECONDARY_VM_EXEC_CONTROL,
5348 vmx_secondary_exec_control(vmx)); 5391 vmx->secondary_exec_control);
5349 } 5392 }
5350 5393
5351 if (kvm_vcpu_apicv_active(&vmx->vcpu)) { 5394 if (kvm_vcpu_apicv_active(&vmx->vcpu)) {
@@ -9623,47 +9666,12 @@ static void nested_vmx_cr_fixed1_bits_update(struct kvm_vcpu *vcpu)
9623static void vmx_cpuid_update(struct kvm_vcpu *vcpu) 9666static void vmx_cpuid_update(struct kvm_vcpu *vcpu)
9624{ 9667{
9625 struct vcpu_vmx *vmx = to_vmx(vcpu); 9668 struct vcpu_vmx *vmx = to_vmx(vcpu);
9626 u32 secondary_exec_ctl = vmx_secondary_exec_control(vmx);
9627
9628 if (vmx_rdtscp_supported()) {
9629 bool rdtscp_enabled = guest_cpuid_has(vcpu, X86_FEATURE_RDTSCP);
9630 if (!rdtscp_enabled)
9631 secondary_exec_ctl &= ~SECONDARY_EXEC_RDTSCP;
9632
9633 if (nested) {
9634 if (rdtscp_enabled)
9635 vmx->nested.nested_vmx_secondary_ctls_high |=
9636 SECONDARY_EXEC_RDTSCP;
9637 else
9638 vmx->nested.nested_vmx_secondary_ctls_high &=
9639 ~SECONDARY_EXEC_RDTSCP;
9640 }
9641 }
9642
9643 if (vmx_invpcid_supported()) {
9644 /* Exposing INVPCID only when PCID is exposed */
9645 bool invpcid_enabled =
9646 guest_cpuid_has(vcpu, X86_FEATURE_INVPCID) &&
9647 guest_cpuid_has(vcpu, X86_FEATURE_PCID);
9648
9649 if (!invpcid_enabled) {
9650 secondary_exec_ctl &= ~SECONDARY_EXEC_ENABLE_INVPCID;
9651 guest_cpuid_clear(vcpu, X86_FEATURE_INVPCID);
9652 }
9653 9669
9654 if (nested) { 9670 if (cpu_has_secondary_exec_ctrls()) {
9655 if (invpcid_enabled) 9671 vmx_compute_secondary_exec_control(vmx);
9656 vmx->nested.nested_vmx_secondary_ctls_high |= 9672 vmcs_set_secondary_exec_control(vmx->secondary_exec_control);
9657 SECONDARY_EXEC_ENABLE_INVPCID;
9658 else
9659 vmx->nested.nested_vmx_secondary_ctls_high &=
9660 ~SECONDARY_EXEC_ENABLE_INVPCID;
9661 }
9662 } 9673 }
9663 9674
9664 if (cpu_has_secondary_exec_ctrls())
9665 vmcs_set_secondary_exec_control(secondary_exec_ctl);
9666
9667 if (nested_vmx_allowed(vcpu)) 9675 if (nested_vmx_allowed(vcpu))
9668 to_vmx(vcpu)->msr_ia32_feature_control_valid_bits |= 9676 to_vmx(vcpu)->msr_ia32_feature_control_valid_bits |=
9669 FEATURE_CONTROL_VMXON_ENABLED_OUTSIDE_SMX; 9677 FEATURE_CONTROL_VMXON_ENABLED_OUTSIDE_SMX;
@@ -10356,7 +10364,7 @@ static int prepare_vmcs02(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12,
10356 enable_ept ? vmcs12->page_fault_error_code_match : 0); 10364 enable_ept ? vmcs12->page_fault_error_code_match : 0);
10357 10365
10358 if (cpu_has_secondary_exec_ctrls()) { 10366 if (cpu_has_secondary_exec_ctrls()) {
10359 exec_control = vmx_secondary_exec_control(vmx); 10367 exec_control = vmx->secondary_exec_control;
10360 10368
10361 /* Take the following fields only from vmcs12 */ 10369 /* Take the following fields only from vmcs12 */
10362 exec_control &= ~(SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES | 10370 exec_control &= ~(SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES |