Skip to content

Commit 80154d7

Browse files
committed
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 <[email protected]>
1 parent 640bd6e commit 80154d7

File tree

1 file changed

+54
-46
lines changed

1 file changed

+54
-46
lines changed

arch/x86/kvm/vmx.c

Lines changed: 54 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -576,6 +576,8 @@ struct vcpu_vmx {
576576
#endif
577577
u32 vm_entry_controls_shadow;
578578
u32 vm_exit_controls_shadow;
579+
u32 secondary_exec_control;
580+
579581
/*
580582
* loaded_vmcs points to the VMCS currently used in this vcpu. For a
581583
* non-nested (L1) guest, it always points to vmcs01. For a nested
@@ -2807,15 +2809,17 @@ static void nested_vmx_setup_ctls_msrs(struct vcpu_vmx *vmx)
28072809
vmx->nested.nested_vmx_procbased_ctls_low &=
28082810
~(CPU_BASED_CR3_LOAD_EXITING | CPU_BASED_CR3_STORE_EXITING);
28092811

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+
*/
28112816
rdmsr(MSR_IA32_VMX_PROCBASED_CTLS2,
28122817
vmx->nested.nested_vmx_secondary_ctls_low,
28132818
vmx->nested.nested_vmx_secondary_ctls_high);
28142819
vmx->nested.nested_vmx_secondary_ctls_low = 0;
28152820
vmx->nested.nested_vmx_secondary_ctls_high &=
28162821
SECONDARY_EXEC_RDRAND | SECONDARY_EXEC_RDSEED |
28172822
SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES |
2818-
SECONDARY_EXEC_RDTSCP |
28192823
SECONDARY_EXEC_DESC |
28202824
SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE |
28212825
SECONDARY_EXEC_APIC_REGISTER_VIRT |
@@ -5269,10 +5273,12 @@ static u32 vmx_exec_control(struct vcpu_vmx *vmx)
52695273
return exec_control;
52705274
}
52715275

5272-
static u32 vmx_secondary_exec_control(struct vcpu_vmx *vmx)
5276+
static void vmx_compute_secondary_exec_control(struct vcpu_vmx *vmx)
52735277
{
5278+
struct kvm_vcpu *vcpu = &vmx->vcpu;
5279+
52745280
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))
52765282
exec_control &= ~SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES;
52775283
if (vmx->vpid == 0)
52785284
exec_control &= ~SECONDARY_EXEC_ENABLE_VPID;
@@ -5286,7 +5292,7 @@ static u32 vmx_secondary_exec_control(struct vcpu_vmx *vmx)
52865292
exec_control &= ~SECONDARY_EXEC_UNRESTRICTED_GUEST;
52875293
if (!ple_gap)
52885294
exec_control &= ~SECONDARY_EXEC_PAUSE_LOOP_EXITING;
5289-
if (!kvm_vcpu_apicv_active(&vmx->vcpu))
5295+
if (!kvm_vcpu_apicv_active(vcpu))
52905296
exec_control &= ~(SECONDARY_EXEC_APIC_REGISTER_VIRT |
52915297
SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY);
52925298
exec_control &= ~SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE;
@@ -5300,7 +5306,43 @@ static u32 vmx_secondary_exec_control(struct vcpu_vmx *vmx)
53005306
if (!enable_pml)
53015307
exec_control &= ~SECONDARY_EXEC_ENABLE_PML;
53025308

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;
53045346
}
53055347

53065348
static void ept_set_mmio_spte_mask(void)
@@ -5344,8 +5386,9 @@ static int vmx_vcpu_setup(struct vcpu_vmx *vmx)
53445386
vmcs_write32(CPU_BASED_VM_EXEC_CONTROL, vmx_exec_control(vmx));
53455387

53465388
if (cpu_has_secondary_exec_ctrls()) {
5389+
vmx_compute_secondary_exec_control(vmx);
53475390
vmcs_write32(SECONDARY_VM_EXEC_CONTROL,
5348-
vmx_secondary_exec_control(vmx));
5391+
vmx->secondary_exec_control);
53495392
}
53505393

53515394
if (kvm_vcpu_apicv_active(&vmx->vcpu)) {
@@ -9623,47 +9666,12 @@ static void nested_vmx_cr_fixed1_bits_update(struct kvm_vcpu *vcpu)
96239666
static void vmx_cpuid_update(struct kvm_vcpu *vcpu)
96249667
{
96259668
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-
}
96539669

9654-
if (nested) {
9655-
if (invpcid_enabled)
9656-
vmx->nested.nested_vmx_secondary_ctls_high |=
9657-
SECONDARY_EXEC_ENABLE_INVPCID;
9658-
else
9659-
vmx->nested.nested_vmx_secondary_ctls_high &=
9660-
~SECONDARY_EXEC_ENABLE_INVPCID;
9661-
}
9670+
if (cpu_has_secondary_exec_ctrls()) {
9671+
vmx_compute_secondary_exec_control(vmx);
9672+
vmcs_set_secondary_exec_control(vmx->secondary_exec_control);
96629673
}
96639674

9664-
if (cpu_has_secondary_exec_ctrls())
9665-
vmcs_set_secondary_exec_control(secondary_exec_ctl);
9666-
96679675
if (nested_vmx_allowed(vcpu))
96689676
to_vmx(vcpu)->msr_ia32_feature_control_valid_bits |=
96699677
FEATURE_CONTROL_VMXON_ENABLED_OUTSIDE_SMX;
@@ -10356,7 +10364,7 @@ static int prepare_vmcs02(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12,
1035610364
enable_ept ? vmcs12->page_fault_error_code_match : 0);
1035710365

1035810366
if (cpu_has_secondary_exec_ctrls()) {
10359-
exec_control = vmx_secondary_exec_control(vmx);
10367+
exec_control = vmx->secondary_exec_control;
1036010368

1036110369
/* Take the following fields only from vmcs12 */
1036210370
exec_control &= ~(SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES |

0 commit comments

Comments
 (0)