diff options
author | Paolo Bonzini <pbonzini@redhat.com> | 2017-08-24 07:55:35 -0400 |
---|---|---|
committer | Paolo Bonzini <pbonzini@redhat.com> | 2017-08-24 09:35:14 -0400 |
commit | 80154d77c922d0f9bb1e4d115ff760c066c12d8f (patch) | |
tree | 44a3b127ce9e25c58528bd44990ca9624260667c | |
parent | 640bd6e5752274f7dbd2a0a6642fe2db85813bd9 (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.c | 100 |
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 | ||
5272 | static u32 vmx_secondary_exec_control(struct vcpu_vmx *vmx) | 5276 | static 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 | ||
5306 | static void ept_set_mmio_spte_mask(void) | 5348 | static 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) | |||
9623 | static void vmx_cpuid_update(struct kvm_vcpu *vcpu) | 9666 | static 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 | |