Skip to content

Commit efebf0a

Browse files
Liran Alonbonzini
authored andcommitted
KVM: nVMX: Do not flush TLB on L1<->L2 transitions if L1 uses VPID and EPT
If L1 uses VPID, it expects TLB to not be flushed on L1<->L2 transitions. However, code currently flushes TLB nonetheless if we didn't allocate a vpid02 for L2. As in this case, vmcs02->vpid == vmcs01->vpid == vmx->vpid. But, if L1 uses EPT, TLB entires populated by L2 are tagged with EPTP02 while TLB entries populated by L1 are tagged with EPTP01. Therefore, we can also avoid TLB flush if L1 uses VPID and EPT. Reviewed-by: Mihai Carabas <mihai.carabas@oracle.com> Reviewed-by: Darren Kenny <darren.kenny@oracle.com> Reviewed-by: Nikita Leshenko <nikita.leshchenko@oracle.com> Signed-off-by: Liran Alon <liran.alon@oracle.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
1 parent 327c072 commit efebf0a

File tree

1 file changed

+27
-10
lines changed

1 file changed

+27
-10
lines changed

arch/x86/kvm/vmx.c

Lines changed: 27 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11964,6 +11964,25 @@ static int nested_vmx_load_cr3(struct kvm_vcpu *vcpu, unsigned long cr3, bool ne
1196411964
return 0;
1196511965
}
1196611966

11967+
/*
11968+
* Returns if KVM is able to config CPU to tag TLB entries
11969+
* populated by L2 differently than TLB entries populated
11970+
* by L1.
11971+
*
11972+
* If L1 uses EPT, then TLB entries are tagged with different EPTP.
11973+
*
11974+
* If L1 uses VPID and we allocated a vpid02, TLB entries are tagged
11975+
* with different VPID (L1 entries are tagged with vmx->vpid
11976+
* while L2 entries are tagged with vmx->nested.vpid02).
11977+
*/
11978+
static bool nested_has_guest_tlb_tag(struct kvm_vcpu *vcpu)
11979+
{
11980+
struct vmcs12 *vmcs12 = get_vmcs12(vcpu);
11981+
11982+
return nested_cpu_has_ept(vmcs12) ||
11983+
(nested_cpu_has_vpid(vmcs12) && to_vmx(vcpu)->nested.vpid02);
11984+
}
11985+
1196711986
static void prepare_vmcs02_full(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12)
1196811987
{
1196911988
struct vcpu_vmx *vmx = to_vmx(vcpu);
@@ -12292,10 +12311,10 @@ static int prepare_vmcs02(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12,
1229212311
* influence global bitmap(for vpid01 and vpid02 allocation)
1229312312
* even if spawn a lot of nested vCPUs.
1229412313
*/
12295-
if (nested_cpu_has_vpid(vmcs12) && vmx->nested.vpid02) {
12314+
if (nested_cpu_has_vpid(vmcs12) && nested_has_guest_tlb_tag(vcpu)) {
1229612315
if (vmcs12->virtual_processor_id != vmx->nested.last_vpid) {
1229712316
vmx->nested.last_vpid = vmcs12->virtual_processor_id;
12298-
__vmx_flush_tlb(vcpu, vmx->nested.vpid02, false);
12317+
__vmx_flush_tlb(vcpu, nested_get_vpid02(vcpu), false);
1229912318
}
1230012319
} else {
1230112320
/*
@@ -13194,23 +13213,21 @@ static void load_vmcs12_host_state(struct kvm_vcpu *vcpu,
1319413213
load_vmcs12_mmu_host_state(vcpu, vmcs12);
1319513214

1319613215
/*
13197-
* If vmcs01 don't use VPID, CPU flushes TLB on every
13216+
* If vmcs01 doesn't use VPID, CPU flushes TLB on every
1319813217
* VMEntry/VMExit. Thus, no need to flush TLB.
1319913218
*
13200-
* If vmcs12 uses VPID, TLB entries populated by L2 are
13201-
* tagged with vmx->nested.vpid02 while L1 entries are tagged
13202-
* with vmx->vpid. Thus, no need to flush TLB.
13219+
* If vmcs12 doesn't use VPID, L1 expects TLB to be
13220+
* flushed on every VMEntry/VMExit.
1320313221
*
13204-
* Therefore, flush TLB only in case vmcs01 uses VPID and
13205-
* vmcs12 don't use VPID as in this case L1 & L2 TLB entries
13206-
* are both tagged with vmx->vpid.
13222+
* Otherwise, we can preserve TLB entries as long as we are
13223+
* able to tag L1 TLB entries differently than L2 TLB entries.
1320713224
*
1320813225
* If vmcs12 uses EPT, we need to execute this flush on EPTP01
1320913226
* and therefore we request the TLB flush to happen only after VMCS EPTP
1321013227
* has been set by KVM_REQ_LOAD_CR3.
1321113228
*/
1321213229
if (enable_vpid &&
13213-
!(nested_cpu_has_vpid(vmcs12) && to_vmx(vcpu)->nested.vpid02)) {
13230+
(!nested_cpu_has_vpid(vmcs12) || !nested_has_guest_tlb_tag(vcpu))) {
1321413231
kvm_make_request(KVM_REQ_TLB_FLUSH, vcpu);
1321513232
}
1321613233

0 commit comments

Comments
 (0)