@@ -8660,11 +8660,26 @@ static int vmx_get_lpage_level(void)
return PT_PDPE_LEVEL;
}
+static void vmcs_set_secondary_exec_control(u32 new_ctl)
+{
+ /*
+ * These bits in the secondary execution controls field
+ * are dynamic, the others are mostly based on the hypervisor
+ * architecture and the guest's CPUID. Do not touch the
+ * dynamic bits.
+ */
+ u32 mask = SECONDARY_EXEC_ENABLE_PML | SECONDARY_EXEC_SHADOW_VMCS;
+ u32 cur_ctl = vmcs_read32(SECONDARY_EXEC_CONTROL);
+
+ vmcs_write32(SECONDARY_EXEC_CONTROL,
+ (new_ctl & ~mask) | (cur_ctl & mask));
+}
+
static void vmx_cpuid_update(struct kvm_vcpu *vcpu)
{
struct kvm_cpuid_entry2 *best;
struct vcpu_vmx *vmx = to_vmx(vcpu);
- u32 clear_exe_ctrl = 0;
+ u32 secondary_exec_ctl = vmx_secondary_exec_control(vmx);
vmx->rdtscp_enabled = false;
if (vmx_rdtscp_supported()) {
@@ -8672,7 +8681,7 @@ static void vmx_cpuid_update(struct kvm_vcpu *vcpu)
if (best && (best->edx & bit(X86_FEATURE_RDTSCP)))
vmx->rdtscp_enabled = true;
else
- clear_exe_ctrl |= SECONDARY_EXEC_RDTSCP;
+ secondary_exec_ctl &= ~SECONDARY_EXEC_RDTSCP;
if (nested) {
if (vmx->rdtscp_enabled)
@@ -8689,18 +8698,13 @@ static void vmx_cpuid_update(struct kvm_vcpu *vcpu)
if (vmx_invpcid_supported() &&
(!best || !(best->ebx & bit(X86_FEATURE_INVPCID)) ||
!guest_cpuid_has_pcid(vcpu))) {
- clear_exe_ctrl |= SECONDARY_EXEC_ENABLE_INVPCID;
+ secondary_exec_ctl &= ~SECONDARY_EXEC_ENABLE_INVPCID;
if (best)
best->ebx &= ~bit(X86_FEATURE_INVPCID);
}
- if (clear_exe_ctrl) {
- u32 exec_ctl = vmcs_read32(SECONDARY_VM_EXEC_CONTROL);
-
- exec_ctl &= ~clear_exe_ctrl;
- vmcs_write32(SECONDARY_VM_EXEC_CONTROL, exec_ctl);
- }
+ vmcs_set_secondary_exec_control(secondary_exec_ctl);
if (static_cpu_has(X86_FEATURE_PCOMMIT) && nested) {
if (guest_cpuid_has_pcommit(vcpu))