diff options
author | Sean Christopherson <sean.j.christopherson@intel.com> | 2019-05-07 15:17:57 -0400 |
---|---|---|
committer | Paolo Bonzini <pbonzini@redhat.com> | 2019-06-18 05:47:42 -0400 |
commit | fe7f895dae4fa5725c0459b316b3e9ee814d2583 (patch) | |
tree | d1a559e0d41ecd20c2ae872fc946bd29194e8186 | |
parent | 2183f5645ae7e074ed1777f3de9a782dd23db248 (diff) |
KVM: VMX: Shadow VMCS secondary execution controls
Prepare to shadow all major control fields on a per-VMCS basis, which
allows KVM to avoid costly VMWRITEs when switching between vmcs01 and
vmcs02.
Signed-off-by: Sean Christopherson <sean.j.christopherson@intel.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
-rw-r--r-- | arch/x86/kvm/vmx/nested.c | 12 | ||||
-rw-r--r-- | arch/x86/kvm/vmx/vmx.c | 40 | ||||
-rw-r--r-- | arch/x86/kvm/vmx/vmx.h | 2 |
3 files changed, 28 insertions, 26 deletions
diff --git a/arch/x86/kvm/vmx/nested.c b/arch/x86/kvm/vmx/nested.c index 3f80df186476..21cb6cd88765 100644 --- a/arch/x86/kvm/vmx/nested.c +++ b/arch/x86/kvm/vmx/nested.c | |||
@@ -192,7 +192,7 @@ static void nested_vmx_abort(struct kvm_vcpu *vcpu, u32 indicator) | |||
192 | 192 | ||
193 | static void vmx_disable_shadow_vmcs(struct vcpu_vmx *vmx) | 193 | static void vmx_disable_shadow_vmcs(struct vcpu_vmx *vmx) |
194 | { | 194 | { |
195 | vmcs_clear_bits(SECONDARY_VM_EXEC_CONTROL, SECONDARY_EXEC_SHADOW_VMCS); | 195 | secondary_exec_controls_clearbit(vmx, SECONDARY_EXEC_SHADOW_VMCS); |
196 | vmcs_write64(VMCS_LINK_POINTER, -1ull); | 196 | vmcs_write64(VMCS_LINK_POINTER, -1ull); |
197 | } | 197 | } |
198 | 198 | ||
@@ -287,6 +287,7 @@ static void vmx_switch_vmcs(struct kvm_vcpu *vcpu, struct loaded_vmcs *vmcs) | |||
287 | vm_exit_controls_reset_shadow(vmx); | 287 | vm_exit_controls_reset_shadow(vmx); |
288 | pin_controls_reset_shadow(vmx); | 288 | pin_controls_reset_shadow(vmx); |
289 | exec_controls_reset_shadow(vmx); | 289 | exec_controls_reset_shadow(vmx); |
290 | secondary_exec_controls_reset_shadow(vmx); | ||
290 | vmx_segment_cache_clear(vmx); | 291 | vmx_segment_cache_clear(vmx); |
291 | } | 292 | } |
292 | 293 | ||
@@ -2083,7 +2084,7 @@ static void prepare_vmcs02_early(struct vcpu_vmx *vmx, struct vmcs12 *vmcs12) | |||
2083 | vmcs_write16(GUEST_INTR_STATUS, | 2084 | vmcs_write16(GUEST_INTR_STATUS, |
2084 | vmcs12->guest_intr_status); | 2085 | vmcs12->guest_intr_status); |
2085 | 2086 | ||
2086 | vmcs_write32(SECONDARY_VM_EXEC_CONTROL, exec_control); | 2087 | secondary_exec_controls_init(vmx, exec_control); |
2087 | } | 2088 | } |
2088 | 2089 | ||
2089 | /* | 2090 | /* |
@@ -2853,8 +2854,8 @@ static void nested_get_vmcs12_pages(struct kvm_vcpu *vcpu) | |||
2853 | hpa = page_to_phys(vmx->nested.apic_access_page); | 2854 | hpa = page_to_phys(vmx->nested.apic_access_page); |
2854 | vmcs_write64(APIC_ACCESS_ADDR, hpa); | 2855 | vmcs_write64(APIC_ACCESS_ADDR, hpa); |
2855 | } else { | 2856 | } else { |
2856 | vmcs_clear_bits(SECONDARY_VM_EXEC_CONTROL, | 2857 | secondary_exec_controls_clearbit(vmx, |
2857 | SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES); | 2858 | SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES); |
2858 | } | 2859 | } |
2859 | } | 2860 | } |
2860 | 2861 | ||
@@ -4667,8 +4668,7 @@ static void set_current_vmptr(struct vcpu_vmx *vmx, gpa_t vmptr) | |||
4667 | { | 4668 | { |
4668 | vmx->nested.current_vmptr = vmptr; | 4669 | vmx->nested.current_vmptr = vmptr; |
4669 | if (enable_shadow_vmcs) { | 4670 | if (enable_shadow_vmcs) { |
4670 | vmcs_set_bits(SECONDARY_VM_EXEC_CONTROL, | 4671 | secondary_exec_controls_setbit(vmx, SECONDARY_EXEC_SHADOW_VMCS); |
4671 | SECONDARY_EXEC_SHADOW_VMCS); | ||
4672 | vmcs_write64(VMCS_LINK_POINTER, | 4672 | vmcs_write64(VMCS_LINK_POINTER, |
4673 | __pa(vmx->vmcs01.shadow_vmcs)); | 4673 | __pa(vmx->vmcs01.shadow_vmcs)); |
4674 | vmx->nested.need_vmcs12_to_shadow_sync = true; | 4674 | vmx->nested.need_vmcs12_to_shadow_sync = true; |
diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c index a2c6f63d2adc..8c1cbc19af97 100644 --- a/arch/x86/kvm/vmx/vmx.c +++ b/arch/x86/kvm/vmx/vmx.c | |||
@@ -2909,6 +2909,7 @@ void vmx_set_cr3(struct kvm_vcpu *vcpu, unsigned long cr3) | |||
2909 | 2909 | ||
2910 | int vmx_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4) | 2910 | int vmx_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4) |
2911 | { | 2911 | { |
2912 | struct vcpu_vmx *vmx = to_vmx(vcpu); | ||
2912 | /* | 2913 | /* |
2913 | * Pass through host's Machine Check Enable value to hw_cr4, which | 2914 | * Pass through host's Machine Check Enable value to hw_cr4, which |
2914 | * is in force while we are in guest mode. Do not let guests control | 2915 | * is in force while we are in guest mode. Do not let guests control |
@@ -2919,20 +2920,19 @@ int vmx_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4) | |||
2919 | hw_cr4 = (cr4_read_shadow() & X86_CR4_MCE) | (cr4 & ~X86_CR4_MCE); | 2920 | hw_cr4 = (cr4_read_shadow() & X86_CR4_MCE) | (cr4 & ~X86_CR4_MCE); |
2920 | if (enable_unrestricted_guest) | 2921 | if (enable_unrestricted_guest) |
2921 | hw_cr4 |= KVM_VM_CR4_ALWAYS_ON_UNRESTRICTED_GUEST; | 2922 | hw_cr4 |= KVM_VM_CR4_ALWAYS_ON_UNRESTRICTED_GUEST; |
2922 | else if (to_vmx(vcpu)->rmode.vm86_active) | 2923 | else if (vmx->rmode.vm86_active) |
2923 | hw_cr4 |= KVM_RMODE_VM_CR4_ALWAYS_ON; | 2924 | hw_cr4 |= KVM_RMODE_VM_CR4_ALWAYS_ON; |
2924 | else | 2925 | else |
2925 | hw_cr4 |= KVM_PMODE_VM_CR4_ALWAYS_ON; | 2926 | hw_cr4 |= KVM_PMODE_VM_CR4_ALWAYS_ON; |
2926 | 2927 | ||
2927 | if (!boot_cpu_has(X86_FEATURE_UMIP) && vmx_umip_emulated()) { | 2928 | if (!boot_cpu_has(X86_FEATURE_UMIP) && vmx_umip_emulated()) { |
2928 | if (cr4 & X86_CR4_UMIP) { | 2929 | if (cr4 & X86_CR4_UMIP) { |
2929 | vmcs_set_bits(SECONDARY_VM_EXEC_CONTROL, | 2930 | secondary_exec_controls_setbit(vmx, SECONDARY_EXEC_DESC); |
2930 | SECONDARY_EXEC_DESC); | ||
2931 | hw_cr4 &= ~X86_CR4_UMIP; | 2931 | hw_cr4 &= ~X86_CR4_UMIP; |
2932 | } else if (!is_guest_mode(vcpu) || | 2932 | } else if (!is_guest_mode(vcpu) || |
2933 | !nested_cpu_has2(get_vmcs12(vcpu), SECONDARY_EXEC_DESC)) | 2933 | !nested_cpu_has2(get_vmcs12(vcpu), SECONDARY_EXEC_DESC)) { |
2934 | vmcs_clear_bits(SECONDARY_VM_EXEC_CONTROL, | 2934 | secondary_exec_controls_clearbit(vmx, SECONDARY_EXEC_DESC); |
2935 | SECONDARY_EXEC_DESC); | 2935 | } |
2936 | } | 2936 | } |
2937 | 2937 | ||
2938 | if (cr4 & X86_CR4_VMXE) { | 2938 | if (cr4 & X86_CR4_VMXE) { |
@@ -2947,7 +2947,7 @@ int vmx_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4) | |||
2947 | return 1; | 2947 | return 1; |
2948 | } | 2948 | } |
2949 | 2949 | ||
2950 | if (to_vmx(vcpu)->nested.vmxon && !nested_cr4_valid(vcpu, cr4)) | 2950 | if (vmx->nested.vmxon && !nested_cr4_valid(vcpu, cr4)) |
2951 | return 1; | 2951 | return 1; |
2952 | 2952 | ||
2953 | vcpu->arch.cr4 = cr4; | 2953 | vcpu->arch.cr4 = cr4; |
@@ -3565,7 +3565,7 @@ static u8 vmx_msr_bitmap_mode(struct kvm_vcpu *vcpu) | |||
3565 | u8 mode = 0; | 3565 | u8 mode = 0; |
3566 | 3566 | ||
3567 | if (cpu_has_secondary_exec_ctrls() && | 3567 | if (cpu_has_secondary_exec_ctrls() && |
3568 | (vmcs_read32(SECONDARY_VM_EXEC_CONTROL) & | 3568 | (secondary_exec_controls_get(to_vmx(vcpu)) & |
3569 | SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE)) { | 3569 | SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE)) { |
3570 | mode |= MSR_BITMAP_MODE_X2APIC; | 3570 | mode |= MSR_BITMAP_MODE_X2APIC; |
3571 | if (enable_apicv && kvm_vcpu_apicv_active(vcpu)) | 3571 | if (enable_apicv && kvm_vcpu_apicv_active(vcpu)) |
@@ -3845,11 +3845,11 @@ static void vmx_refresh_apicv_exec_ctrl(struct kvm_vcpu *vcpu) | |||
3845 | pin_controls_set(vmx, vmx_pin_based_exec_ctrl(vmx)); | 3845 | pin_controls_set(vmx, vmx_pin_based_exec_ctrl(vmx)); |
3846 | if (cpu_has_secondary_exec_ctrls()) { | 3846 | if (cpu_has_secondary_exec_ctrls()) { |
3847 | if (kvm_vcpu_apicv_active(vcpu)) | 3847 | if (kvm_vcpu_apicv_active(vcpu)) |
3848 | vmcs_set_bits(SECONDARY_VM_EXEC_CONTROL, | 3848 | secondary_exec_controls_setbit(vmx, |
3849 | SECONDARY_EXEC_APIC_REGISTER_VIRT | | 3849 | SECONDARY_EXEC_APIC_REGISTER_VIRT | |
3850 | SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY); | 3850 | SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY); |
3851 | else | 3851 | else |
3852 | vmcs_clear_bits(SECONDARY_VM_EXEC_CONTROL, | 3852 | secondary_exec_controls_clearbit(vmx, |
3853 | SECONDARY_EXEC_APIC_REGISTER_VIRT | | 3853 | SECONDARY_EXEC_APIC_REGISTER_VIRT | |
3854 | SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY); | 3854 | SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY); |
3855 | } | 3855 | } |
@@ -4047,8 +4047,7 @@ static void vmx_vcpu_setup(struct vcpu_vmx *vmx) | |||
4047 | 4047 | ||
4048 | if (cpu_has_secondary_exec_ctrls()) { | 4048 | if (cpu_has_secondary_exec_ctrls()) { |
4049 | vmx_compute_secondary_exec_control(vmx); | 4049 | vmx_compute_secondary_exec_control(vmx); |
4050 | vmcs_write32(SECONDARY_VM_EXEC_CONTROL, | 4050 | secondary_exec_controls_init(vmx, vmx->secondary_exec_control); |
4051 | vmx->secondary_exec_control); | ||
4052 | } | 4051 | } |
4053 | 4052 | ||
4054 | if (kvm_vcpu_apicv_active(&vmx->vcpu)) { | 4053 | if (kvm_vcpu_apicv_active(&vmx->vcpu)) { |
@@ -5969,6 +5968,7 @@ static void update_cr8_intercept(struct kvm_vcpu *vcpu, int tpr, int irr) | |||
5969 | 5968 | ||
5970 | void vmx_set_virtual_apic_mode(struct kvm_vcpu *vcpu) | 5969 | void vmx_set_virtual_apic_mode(struct kvm_vcpu *vcpu) |
5971 | { | 5970 | { |
5971 | struct vcpu_vmx *vmx = to_vmx(vcpu); | ||
5972 | u32 sec_exec_control; | 5972 | u32 sec_exec_control; |
5973 | 5973 | ||
5974 | if (!lapic_in_kernel(vcpu)) | 5974 | if (!lapic_in_kernel(vcpu)) |
@@ -5980,11 +5980,11 @@ void vmx_set_virtual_apic_mode(struct kvm_vcpu *vcpu) | |||
5980 | 5980 | ||
5981 | /* Postpone execution until vmcs01 is the current VMCS. */ | 5981 | /* Postpone execution until vmcs01 is the current VMCS. */ |
5982 | if (is_guest_mode(vcpu)) { | 5982 | if (is_guest_mode(vcpu)) { |
5983 | to_vmx(vcpu)->nested.change_vmcs01_virtual_apic_mode = true; | 5983 | vmx->nested.change_vmcs01_virtual_apic_mode = true; |
5984 | return; | 5984 | return; |
5985 | } | 5985 | } |
5986 | 5986 | ||
5987 | sec_exec_control = vmcs_read32(SECONDARY_VM_EXEC_CONTROL); | 5987 | sec_exec_control = secondary_exec_controls_get(vmx); |
5988 | sec_exec_control &= ~(SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES | | 5988 | sec_exec_control &= ~(SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES | |
5989 | SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE); | 5989 | SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE); |
5990 | 5990 | ||
@@ -6006,7 +6006,7 @@ void vmx_set_virtual_apic_mode(struct kvm_vcpu *vcpu) | |||
6006 | SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE; | 6006 | SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE; |
6007 | break; | 6007 | break; |
6008 | } | 6008 | } |
6009 | vmcs_write32(SECONDARY_VM_EXEC_CONTROL, sec_exec_control); | 6009 | secondary_exec_controls_set(vmx, sec_exec_control); |
6010 | 6010 | ||
6011 | vmx_update_msr_bitmap(vcpu); | 6011 | vmx_update_msr_bitmap(vcpu); |
6012 | } | 6012 | } |
@@ -6827,7 +6827,7 @@ static int vmx_get_lpage_level(void) | |||
6827 | return PT_PDPE_LEVEL; | 6827 | return PT_PDPE_LEVEL; |
6828 | } | 6828 | } |
6829 | 6829 | ||
6830 | static void vmcs_set_secondary_exec_control(u32 new_ctl) | 6830 | static void vmcs_set_secondary_exec_control(struct vcpu_vmx *vmx) |
6831 | { | 6831 | { |
6832 | /* | 6832 | /* |
6833 | * These bits in the secondary execution controls field | 6833 | * These bits in the secondary execution controls field |
@@ -6841,10 +6841,10 @@ static void vmcs_set_secondary_exec_control(u32 new_ctl) | |||
6841 | SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES | | 6841 | SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES | |
6842 | SECONDARY_EXEC_DESC; | 6842 | SECONDARY_EXEC_DESC; |
6843 | 6843 | ||
6844 | u32 cur_ctl = vmcs_read32(SECONDARY_VM_EXEC_CONTROL); | 6844 | u32 new_ctl = vmx->secondary_exec_control; |
6845 | u32 cur_ctl = secondary_exec_controls_get(vmx); | ||
6845 | 6846 | ||
6846 | vmcs_write32(SECONDARY_VM_EXEC_CONTROL, | 6847 | secondary_exec_controls_set(vmx, (new_ctl & ~mask) | (cur_ctl & mask)); |
6847 | (new_ctl & ~mask) | (cur_ctl & mask)); | ||
6848 | } | 6848 | } |
6849 | 6849 | ||
6850 | /* | 6850 | /* |
@@ -6982,7 +6982,7 @@ static void vmx_cpuid_update(struct kvm_vcpu *vcpu) | |||
6982 | 6982 | ||
6983 | if (cpu_has_secondary_exec_ctrls()) { | 6983 | if (cpu_has_secondary_exec_ctrls()) { |
6984 | vmx_compute_secondary_exec_control(vmx); | 6984 | vmx_compute_secondary_exec_control(vmx); |
6985 | vmcs_set_secondary_exec_control(vmx->secondary_exec_control); | 6985 | vmcs_set_secondary_exec_control(vmx); |
6986 | } | 6986 | } |
6987 | 6987 | ||
6988 | if (nested_vmx_allowed(vcpu)) | 6988 | if (nested_vmx_allowed(vcpu)) |
diff --git a/arch/x86/kvm/vmx/vmx.h b/arch/x86/kvm/vmx/vmx.h index 754cc52f2640..bde6c43eea16 100644 --- a/arch/x86/kvm/vmx/vmx.h +++ b/arch/x86/kvm/vmx/vmx.h | |||
@@ -90,6 +90,7 @@ struct vmx_controls_shadow { | |||
90 | u32 vm_exit; | 90 | u32 vm_exit; |
91 | u32 pin; | 91 | u32 pin; |
92 | u32 exec; | 92 | u32 exec; |
93 | u32 secondary_exec; | ||
93 | }; | 94 | }; |
94 | 95 | ||
95 | /* | 96 | /* |
@@ -427,6 +428,7 @@ BUILD_CONTROLS_SHADOW(vm_entry, VM_ENTRY_CONTROLS) | |||
427 | BUILD_CONTROLS_SHADOW(vm_exit, VM_EXIT_CONTROLS) | 428 | BUILD_CONTROLS_SHADOW(vm_exit, VM_EXIT_CONTROLS) |
428 | BUILD_CONTROLS_SHADOW(pin, PIN_BASED_VM_EXEC_CONTROL) | 429 | BUILD_CONTROLS_SHADOW(pin, PIN_BASED_VM_EXEC_CONTROL) |
429 | BUILD_CONTROLS_SHADOW(exec, CPU_BASED_VM_EXEC_CONTROL) | 430 | BUILD_CONTROLS_SHADOW(exec, CPU_BASED_VM_EXEC_CONTROL) |
431 | BUILD_CONTROLS_SHADOW(secondary_exec, SECONDARY_VM_EXEC_CONTROL) | ||
430 | 432 | ||
431 | static inline void vmx_segment_cache_clear(struct vcpu_vmx *vmx) | 433 | static inline void vmx_segment_cache_clear(struct vcpu_vmx *vmx) |
432 | { | 434 | { |