Alexander Graf aee234
From: Paolo Bonzini <pbonzini@redhat.com>
Alexander Graf aee234
Date: Thu, 24 Aug 2017 13:55:35 +0200
Alexander Graf aee234
Subject: KVM: VMX: cache secondary exec controls
Alexander Graf aee234
Patch-mainline: v4.14-rc1
Alexander Graf aee234
Git-commit: 80154d77c922d0f9bb1e4d115ff760c066c12d8f
Alexander Graf aee234
References: bsc#1077761
Alexander Graf aee234
Alexander Graf aee234
Currently, secondary execution controls are divided in three groups:
Alexander Graf aee234
Alexander Graf aee234
- static, depending mostly on the module arguments or the processor
Alexander Graf aee234
  (vmx_secondary_exec_control)
Alexander Graf aee234
Alexander Graf aee234
- static, depending on CPUID (vmx_cpuid_update)
Alexander Graf aee234
Alexander Graf aee234
- dynamic, depending on nested VMX or local APIC state
Alexander Graf aee234
Alexander Graf aee234
Because walking CPUID is expensive, prepare_vmcs02 is using only
Alexander Graf aee234
the first group.  This however is unnecessarily complicated.  Just
Alexander Graf aee234
cache the static secondary execution controls, and then prepare_vmcs02
Alexander Graf aee234
does not need to compute them every time.  Computation of all static
Alexander Graf aee234
secondary execution controls is now kept in a single function,
Alexander Graf aee234
vmx_compute_secondary_exec_control.
Alexander Graf aee234
Alexander Graf aee234
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Alexander Graf aee234
Acked-by: Alexander Graf <agraf@suse.de>
Alexander Graf aee234
---
Alexander Graf aee234
 arch/x86/kvm/vmx.c |  100 ++++++++++++++++++++++++++++-------------------------
Alexander Graf aee234
 1 file changed, 54 insertions(+), 46 deletions(-)
Alexander Graf aee234
Alexander Graf aee234
--- a/arch/x86/kvm/vmx.c
Alexander Graf aee234
+++ b/arch/x86/kvm/vmx.c
Alexander Graf aee234
@@ -574,6 +574,8 @@
Alexander Graf aee234
 #endif
Alexander Graf aee234
 	u32 vm_entry_controls_shadow;
Alexander Graf aee234
 	u32 vm_exit_controls_shadow;
Alexander Graf aee234
+	u32 secondary_exec_control;
Alexander Graf aee234
+
Alexander Graf aee234
 	/*
Alexander Graf aee234
 	 * loaded_vmcs points to the VMCS currently used in this vcpu. For a
Alexander Graf aee234
 	 * non-nested (L1) guest, it always points to vmcs01. For a nested
Alexander Graf aee234
@@ -2797,7 +2799,10 @@
Alexander Graf aee234
 	vmx->nested.nested_vmx_procbased_ctls_low &=
Alexander Graf aee234
 		~(CPU_BASED_CR3_LOAD_EXITING | CPU_BASED_CR3_STORE_EXITING);
Alexander Graf aee234
 
Alexander Graf aee234
-	/* secondary cpu-based controls */
Alexander Graf aee234
+	/*
Alexander Graf aee234
+	 * secondary cpu-based controls.  Do not include those that
Alexander Graf aee234
+	 * depend on CPUID bits, they are added later by vmx_cpuid_update.
Alexander Graf aee234
+	 */
Alexander Graf aee234
 	rdmsr(MSR_IA32_VMX_PROCBASED_CTLS2,
Alexander Graf aee234
 		vmx->nested.nested_vmx_secondary_ctls_low,
Alexander Graf aee234
 		vmx->nested.nested_vmx_secondary_ctls_high);
Alexander Graf aee234
@@ -2805,7 +2810,6 @@
Alexander Graf aee234
 	vmx->nested.nested_vmx_secondary_ctls_high &=
Alexander Graf aee234
 		SECONDARY_EXEC_RDRAND | SECONDARY_EXEC_RDSEED |
Alexander Graf aee234
 		SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES |
Alexander Graf aee234
-		SECONDARY_EXEC_RDTSCP |
Alexander Graf aee234
 		SECONDARY_EXEC_DESC |
Alexander Graf aee234
 		SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE |
Alexander Graf aee234
 		SECONDARY_EXEC_APIC_REGISTER_VIRT |
Alexander Graf aee234
@@ -5252,10 +5256,12 @@
Alexander Graf aee234
 	return exec_control;
Alexander Graf aee234
 }
Alexander Graf aee234
 
Alexander Graf aee234
-static u32 vmx_secondary_exec_control(struct vcpu_vmx *vmx)
Alexander Graf aee234
+static void vmx_compute_secondary_exec_control(struct vcpu_vmx *vmx)
Alexander Graf aee234
 {
Alexander Graf aee234
+	struct kvm_vcpu *vcpu = &vmx->vcpu;
Alexander Graf aee234
+
Alexander Graf aee234
 	u32 exec_control = vmcs_config.cpu_based_2nd_exec_ctrl;
Alexander Graf aee234
-	if (!cpu_need_virtualize_apic_accesses(&vmx->vcpu))
Alexander Graf aee234
+	if (!cpu_need_virtualize_apic_accesses(vcpu))
Alexander Graf aee234
 		exec_control &= ~SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES;
Alexander Graf aee234
 	if (vmx->vpid == 0)
Alexander Graf aee234
 		exec_control &= ~SECONDARY_EXEC_ENABLE_VPID;
Alexander Graf aee234
@@ -5269,7 +5275,7 @@
Alexander Graf aee234
 		exec_control &= ~SECONDARY_EXEC_UNRESTRICTED_GUEST;
Alexander Graf aee234
 	if (!ple_gap)
Alexander Graf aee234
 		exec_control &= ~SECONDARY_EXEC_PAUSE_LOOP_EXITING;
Alexander Graf aee234
-	if (!kvm_vcpu_apicv_active(&vmx->vcpu))
Alexander Graf aee234
+	if (!kvm_vcpu_apicv_active(vcpu))
Alexander Graf aee234
 		exec_control &= ~(SECONDARY_EXEC_APIC_REGISTER_VIRT |
Alexander Graf aee234
 				  SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY);
Alexander Graf aee234
 	exec_control &= ~SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE;
Alexander Graf aee234
@@ -5283,7 +5289,43 @@
Alexander Graf aee234
 	if (!enable_pml)
Alexander Graf aee234
 		exec_control &= ~SECONDARY_EXEC_ENABLE_PML;
Alexander Graf aee234
 
Alexander Graf aee234
-	return exec_control;
Alexander Graf aee234
+	if (vmx_rdtscp_supported()) {
Alexander Graf aee234
+		bool rdtscp_enabled = guest_cpuid_has(vcpu, X86_FEATURE_RDTSCP);
Alexander Graf aee234
+		if (!rdtscp_enabled)
Alexander Graf aee234
+			exec_control &= ~SECONDARY_EXEC_RDTSCP;
Alexander Graf aee234
+
Alexander Graf aee234
+		if (nested) {
Alexander Graf aee234
+			if (rdtscp_enabled)
Alexander Graf aee234
+				vmx->nested.nested_vmx_secondary_ctls_high |=
Alexander Graf aee234
+					SECONDARY_EXEC_RDTSCP;
Alexander Graf aee234
+			else
Alexander Graf aee234
+				vmx->nested.nested_vmx_secondary_ctls_high &=
Alexander Graf aee234
+					~SECONDARY_EXEC_RDTSCP;
Alexander Graf aee234
+		}
Alexander Graf aee234
+	}
Alexander Graf aee234
+
Alexander Graf aee234
+	if (vmx_invpcid_supported()) {
Alexander Graf aee234
+		/* Exposing INVPCID only when PCID is exposed */
Alexander Graf aee234
+		bool invpcid_enabled =
Alexander Graf aee234
+			guest_cpuid_has(vcpu, X86_FEATURE_INVPCID) &&
Alexander Graf aee234
+			guest_cpuid_has(vcpu, X86_FEATURE_PCID);
Alexander Graf aee234
+
Alexander Graf aee234
+		if (!invpcid_enabled) {
Alexander Graf aee234
+			exec_control &= ~SECONDARY_EXEC_ENABLE_INVPCID;
Alexander Graf aee234
+			guest_cpuid_clear(vcpu, X86_FEATURE_INVPCID);
Alexander Graf aee234
+		}
Alexander Graf aee234
+
Alexander Graf aee234
+		if (nested) {
Alexander Graf aee234
+			if (invpcid_enabled)
Alexander Graf aee234
+				vmx->nested.nested_vmx_secondary_ctls_high |=
Alexander Graf aee234
+					SECONDARY_EXEC_ENABLE_INVPCID;
Alexander Graf aee234
+			else
Alexander Graf aee234
+				vmx->nested.nested_vmx_secondary_ctls_high &=
Alexander Graf aee234
+					~SECONDARY_EXEC_ENABLE_INVPCID;
Alexander Graf aee234
+		}
Alexander Graf aee234
+	}
Alexander Graf aee234
+
Alexander Graf aee234
+	vmx->secondary_exec_control = exec_control;
Alexander Graf aee234
 }
Alexander Graf aee234
 
Alexander Graf aee234
 static void ept_set_mmio_spte_mask(void)
Alexander Graf aee234
@@ -5327,8 +5369,9 @@
Alexander Graf aee234
 	vmcs_write32(CPU_BASED_VM_EXEC_CONTROL, vmx_exec_control(vmx));
Alexander Graf aee234
 
Alexander Graf aee234
 	if (cpu_has_secondary_exec_ctrls()) {
Alexander Graf aee234
+		vmx_compute_secondary_exec_control(vmx);
Alexander Graf aee234
 		vmcs_write32(SECONDARY_VM_EXEC_CONTROL,
Alexander Graf aee234
-				vmx_secondary_exec_control(vmx));
Alexander Graf aee234
+			     vmx->secondary_exec_control);
Alexander Graf aee234
 	}
Alexander Graf aee234
 
Alexander Graf aee234
 	if (kvm_vcpu_apicv_active(&vmx->vcpu)) {
Alexander Graf aee234
@@ -9598,47 +9641,12 @@
Alexander Graf aee234
 static void vmx_cpuid_update(struct kvm_vcpu *vcpu)
Alexander Graf aee234
 {
Alexander Graf aee234
 	struct vcpu_vmx *vmx = to_vmx(vcpu);
Alexander Graf aee234
-	u32 secondary_exec_ctl = vmx_secondary_exec_control(vmx);
Alexander Graf aee234
-
Alexander Graf aee234
-	if (vmx_rdtscp_supported()) {
Alexander Graf aee234
-		bool rdtscp_enabled = guest_cpuid_has(vcpu, X86_FEATURE_RDTSCP);
Alexander Graf aee234
-		if (!rdtscp_enabled)
Alexander Graf aee234
-			secondary_exec_ctl &= ~SECONDARY_EXEC_RDTSCP;
Alexander Graf aee234
-
Alexander Graf aee234
-		if (nested) {
Alexander Graf aee234
-			if (rdtscp_enabled)
Alexander Graf aee234
-				vmx->nested.nested_vmx_secondary_ctls_high |=
Alexander Graf aee234
-					SECONDARY_EXEC_RDTSCP;
Alexander Graf aee234
-			else
Alexander Graf aee234
-				vmx->nested.nested_vmx_secondary_ctls_high &=
Alexander Graf aee234
-					~SECONDARY_EXEC_RDTSCP;
Alexander Graf aee234
-		}
Alexander Graf aee234
-	}
Alexander Graf aee234
-
Alexander Graf aee234
-	if (vmx_invpcid_supported()) {
Alexander Graf aee234
-		/* Exposing INVPCID only when PCID is exposed */
Alexander Graf aee234
-		bool invpcid_enabled =
Alexander Graf aee234
-			guest_cpuid_has(vcpu, X86_FEATURE_INVPCID) &&
Alexander Graf aee234
-			guest_cpuid_has(vcpu, X86_FEATURE_PCID);
Alexander Graf aee234
-
Alexander Graf aee234
-		if (!invpcid_enabled) {
Alexander Graf aee234
-			secondary_exec_ctl &= ~SECONDARY_EXEC_ENABLE_INVPCID;
Alexander Graf aee234
-			guest_cpuid_clear(vcpu, X86_FEATURE_INVPCID);
Alexander Graf aee234
-		}
Alexander Graf aee234
 
Alexander Graf aee234
-		if (nested) {
Alexander Graf aee234
-			if (invpcid_enabled)
Alexander Graf aee234
-				vmx->nested.nested_vmx_secondary_ctls_high |=
Alexander Graf aee234
-					SECONDARY_EXEC_ENABLE_INVPCID;
Alexander Graf aee234
-			else
Alexander Graf aee234
-				vmx->nested.nested_vmx_secondary_ctls_high &=
Alexander Graf aee234
-					~SECONDARY_EXEC_ENABLE_INVPCID;
Alexander Graf aee234
-		}
Alexander Graf aee234
+	if (cpu_has_secondary_exec_ctrls()) {
Alexander Graf aee234
+		vmx_compute_secondary_exec_control(vmx);
Alexander Graf aee234
+		vmcs_set_secondary_exec_control(vmx->secondary_exec_control);
Alexander Graf aee234
 	}
Alexander Graf aee234
 
Alexander Graf aee234
-	if (cpu_has_secondary_exec_ctrls())
Alexander Graf aee234
-		vmcs_set_secondary_exec_control(secondary_exec_ctl);
Alexander Graf aee234
-
Alexander Graf aee234
 	if (nested_vmx_allowed(vcpu))
Alexander Graf aee234
 		to_vmx(vcpu)->msr_ia32_feature_control_valid_bits |=
Alexander Graf aee234
 			FEATURE_CONTROL_VMXON_ENABLED_OUTSIDE_SMX;
Alexander Graf aee234
@@ -10331,7 +10339,7 @@
Alexander Graf aee234
 		enable_ept ? vmcs12->page_fault_error_code_match : 0);
Alexander Graf aee234
 
Alexander Graf aee234
 	if (cpu_has_secondary_exec_ctrls()) {
Alexander Graf aee234
-		exec_control = vmx_secondary_exec_control(vmx);
Alexander Graf aee234
+		exec_control = vmx->secondary_exec_control;
Alexander Graf aee234
 
Alexander Graf aee234
 		/* Take the following fields only from vmcs12 */
Alexander Graf aee234
 		exec_control &= ~(SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES |