|
@@ -861,6 +861,12 @@ static inline bool cpu_has_vmx_rdtscp(void)
|
|
|
SECONDARY_EXEC_RDTSCP;
|
|
|
}
|
|
|
|
|
|
+static inline bool cpu_has_vmx_invpcid(void)
|
|
|
+{
|
|
|
+ return vmcs_config.cpu_based_2nd_exec_ctrl &
|
|
|
+ SECONDARY_EXEC_ENABLE_INVPCID;
|
|
|
+}
|
|
|
+
|
|
|
static inline bool cpu_has_virtual_nmis(void)
|
|
|
{
|
|
|
return vmcs_config.pin_based_exec_ctrl & PIN_BASED_VIRTUAL_NMIS;
|
|
@@ -1751,6 +1757,11 @@ static bool vmx_rdtscp_supported(void)
|
|
|
return cpu_has_vmx_rdtscp();
|
|
|
}
|
|
|
|
|
|
+static bool vmx_invpcid_supported(void)
|
|
|
+{
|
|
|
+ return cpu_has_vmx_invpcid() && enable_ept;
|
|
|
+}
|
|
|
+
|
|
|
/*
|
|
|
* Swap MSR entry in host/guest MSR entry array.
|
|
|
*/
|
|
@@ -2470,7 +2481,8 @@ static __init int setup_vmcs_config(struct vmcs_config *vmcs_conf)
|
|
|
SECONDARY_EXEC_ENABLE_EPT |
|
|
|
SECONDARY_EXEC_UNRESTRICTED_GUEST |
|
|
|
SECONDARY_EXEC_PAUSE_LOOP_EXITING |
|
|
|
- SECONDARY_EXEC_RDTSCP;
|
|
|
+ SECONDARY_EXEC_RDTSCP |
|
|
|
+ SECONDARY_EXEC_ENABLE_INVPCID;
|
|
|
if (adjust_vmx_controls(min2, opt2,
|
|
|
MSR_IA32_VMX_PROCBASED_CTLS2,
|
|
|
&_cpu_based_2nd_exec_control) < 0)
|
|
@@ -3800,6 +3812,8 @@ static u32 vmx_secondary_exec_control(struct vcpu_vmx *vmx)
|
|
|
if (!enable_ept) {
|
|
|
exec_control &= ~SECONDARY_EXEC_ENABLE_EPT;
|
|
|
enable_unrestricted_guest = 0;
|
|
|
+ /* Enable INVPCID for non-ept guests may cause performance regression. */
|
|
|
+ exec_control &= ~SECONDARY_EXEC_ENABLE_INVPCID;
|
|
|
}
|
|
|
if (!enable_unrestricted_guest)
|
|
|
exec_control &= ~SECONDARY_EXEC_UNRESTRICTED_GUEST;
|
|
@@ -6550,6 +6564,23 @@ static void vmx_cpuid_update(struct kvm_vcpu *vcpu)
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+ exec_control = vmcs_read32(SECONDARY_VM_EXEC_CONTROL);
|
|
|
+ /* Exposing INVPCID only when PCID is exposed */
|
|
|
+ best = kvm_find_cpuid_entry(vcpu, 0x7, 0);
|
|
|
+ if (vmx_invpcid_supported() &&
|
|
|
+ best && (best->ecx & bit(X86_FEATURE_INVPCID)) &&
|
|
|
+ guest_cpuid_has_pcid(vcpu)) {
|
|
|
+ exec_control |= SECONDARY_EXEC_ENABLE_INVPCID;
|
|
|
+ vmcs_write32(SECONDARY_VM_EXEC_CONTROL,
|
|
|
+ exec_control);
|
|
|
+ } else {
|
|
|
+ exec_control &= ~SECONDARY_EXEC_ENABLE_INVPCID;
|
|
|
+ vmcs_write32(SECONDARY_VM_EXEC_CONTROL,
|
|
|
+ exec_control);
|
|
|
+ if (best)
|
|
|
+ best->ecx &= ~bit(X86_FEATURE_INVPCID);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
static void vmx_set_supported_cpuid(u32 func, struct kvm_cpuid_entry2 *entry)
|
|
@@ -7284,6 +7315,7 @@ static struct kvm_x86_ops vmx_x86_ops = {
|
|
|
.cpuid_update = vmx_cpuid_update,
|
|
|
|
|
|
.rdtscp_supported = vmx_rdtscp_supported,
|
|
|
+ .invpcid_supported = vmx_invpcid_supported,
|
|
|
|
|
|
.set_supported_cpuid = vmx_set_supported_cpuid,
|
|
|
|