KVM: nVMX: Unconditionally validate CR3 during nested transitions
Unconditionally check the validity of the incoming CR3 during nested VM-Enter/VM-Exit to avoid invoking kvm_read_cr3() in the common case where the guest isn't using PAE paging. If vmcs.GUEST_CR3 hasn't yet been cached (common case), kvm_read_cr3() will trigger a VMREAD. The VMREAD (~30 cycles) alone is likely slower than nested_cr3_valid() (~5 cycles if vcpu->arch.maxphyaddr gets a cache hit), and the poor exchange only gets worse when retpolines are enabled as the call to kvm_x86_ops.cache_reg() will incur a retpoline (60+ cycles). Signed-off-by: Sean Christopherson <sean.j.christopherson@intel.com> Message-Id: <20200502043234.12481-3-sean.j.christopherson@intel.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
parent
56ba77a459
commit
0cc69204e7
@ -1119,21 +1119,20 @@ static bool nested_vmx_transition_mmu_sync(struct kvm_vcpu *vcpu)
|
|||||||
static int nested_vmx_load_cr3(struct kvm_vcpu *vcpu, unsigned long cr3, bool nested_ept,
|
static int nested_vmx_load_cr3(struct kvm_vcpu *vcpu, unsigned long cr3, bool nested_ept,
|
||||||
u32 *entry_failure_code)
|
u32 *entry_failure_code)
|
||||||
{
|
{
|
||||||
if (cr3 != kvm_read_cr3(vcpu) || (!nested_ept && pdptrs_changed(vcpu))) {
|
if (CC(!nested_cr3_valid(vcpu, cr3))) {
|
||||||
if (CC(!nested_cr3_valid(vcpu, cr3))) {
|
*entry_failure_code = ENTRY_FAIL_DEFAULT;
|
||||||
*entry_failure_code = ENTRY_FAIL_DEFAULT;
|
return -EINVAL;
|
||||||
return -EINVAL;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If PAE paging and EPT are both on, CR3 is not used by the CPU and
|
* If PAE paging and EPT are both on, CR3 is not used by the CPU and
|
||||||
* must not be dereferenced.
|
* must not be dereferenced.
|
||||||
*/
|
*/
|
||||||
if (is_pae_paging(vcpu) && !nested_ept) {
|
if (!nested_ept && is_pae_paging(vcpu) &&
|
||||||
if (CC(!load_pdptrs(vcpu, vcpu->arch.walk_mmu, cr3))) {
|
(cr3 != kvm_read_cr3(vcpu) || pdptrs_changed(vcpu))) {
|
||||||
*entry_failure_code = ENTRY_FAIL_PDPTE;
|
if (CC(!load_pdptrs(vcpu, vcpu->arch.walk_mmu, cr3))) {
|
||||||
return -EINVAL;
|
*entry_failure_code = ENTRY_FAIL_PDPTE;
|
||||||
}
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user