Commit b869855b authored by Sean Christopherson's avatar Sean Christopherson Committed by Paolo Bonzini

KVM: x86/mmu: Move fast_cr3_switch() side effects to __kvm_mmu_new_cr3()

Handle the side effects of a fast CR3 (PGD) switch up a level in
__kvm_mmu_new_cr3(), which is the only caller of fast_cr3_switch().

This consolidates handling all side effects in __kvm_mmu_new_cr3()
(where freeing the current root when KVM can't do a fast switch is
already handled), and ameliorates the pain of adding a second boolean in
a future patch to provide a separate "skip" override for the MMU sync.

Cc: Vitaly Kuznetsov <vkuznets@redhat.com>
Signed-off-by: default avatarSean Christopherson <sean.j.christopherson@intel.com>
Message-Id: <20200320212833.3507-31-sean.j.christopherson@intel.com>
Signed-off-by: default avatarPaolo Bonzini <pbonzini@redhat.com>
parent 4de1f9d4
...@@ -4284,8 +4284,7 @@ static bool cached_root_available(struct kvm_vcpu *vcpu, gpa_t new_cr3, ...@@ -4284,8 +4284,7 @@ static bool cached_root_available(struct kvm_vcpu *vcpu, gpa_t new_cr3,
} }
static bool fast_cr3_switch(struct kvm_vcpu *vcpu, gpa_t new_cr3, static bool fast_cr3_switch(struct kvm_vcpu *vcpu, gpa_t new_cr3,
union kvm_mmu_page_role new_role, union kvm_mmu_page_role new_role)
bool skip_tlb_flush)
{ {
struct kvm_mmu *mmu = vcpu->arch.mmu; struct kvm_mmu *mmu = vcpu->arch.mmu;
...@@ -4295,50 +4294,44 @@ static bool fast_cr3_switch(struct kvm_vcpu *vcpu, gpa_t new_cr3, ...@@ -4295,50 +4294,44 @@ static bool fast_cr3_switch(struct kvm_vcpu *vcpu, gpa_t new_cr3,
* later if necessary. * later if necessary.
*/ */
if (mmu->shadow_root_level >= PT64_ROOT_4LEVEL && if (mmu->shadow_root_level >= PT64_ROOT_4LEVEL &&
mmu->root_level >= PT64_ROOT_4LEVEL) { mmu->root_level >= PT64_ROOT_4LEVEL)
if (mmu_check_root(vcpu, new_cr3 >> PAGE_SHIFT)) return !mmu_check_root(vcpu, new_cr3 >> PAGE_SHIFT) &&
cached_root_available(vcpu, new_cr3, new_role);
return false; return false;
}
static void __kvm_mmu_new_cr3(struct kvm_vcpu *vcpu, gpa_t new_cr3,
union kvm_mmu_page_role new_role,
bool skip_tlb_flush)
{
if (!fast_cr3_switch(vcpu, new_cr3, new_role)) {
kvm_mmu_free_roots(vcpu, vcpu->arch.mmu, KVM_MMU_ROOT_CURRENT);
return;
}
if (cached_root_available(vcpu, new_cr3, new_role)) {
/* /*
* It is possible that the cached previous root page is * It's possible that the cached previous root page is obsolete because
* obsolete because of a change in the MMU generation * of a change in the MMU generation number. However, changing the
* number. However, changing the generation number is * generation number is accompanied by KVM_REQ_MMU_RELOAD, which will
* accompanied by KVM_REQ_MMU_RELOAD, which will free * free the root set here and allocate a new one.
* the root set here and allocate a new one.
*/ */
kvm_make_request(KVM_REQ_LOAD_MMU_PGD, vcpu); kvm_make_request(KVM_REQ_LOAD_MMU_PGD, vcpu);
if (!skip_tlb_flush) { if (!skip_tlb_flush) {
kvm_make_request(KVM_REQ_MMU_SYNC, vcpu); kvm_make_request(KVM_REQ_MMU_SYNC, vcpu);
kvm_make_request(KVM_REQ_TLB_FLUSH_CURRENT, vcpu); kvm_make_request(KVM_REQ_TLB_FLUSH_CURRENT, vcpu);
} }
/* /*
* The last MMIO access's GVA and GPA are cached in the * The last MMIO access's GVA and GPA are cached in the VCPU. When
* VCPU. When switching to a new CR3, that GVA->GPA * switching to a new CR3, that GVA->GPA mapping may no longer be
* mapping may no longer be valid. So clear any cached * valid. So clear any cached MMIO info even when we don't need to sync
* MMIO info even when we don't need to sync the shadow * the shadow page tables.
* page tables.
*/ */
vcpu_clear_mmio_info(vcpu, MMIO_GVA_ANY); vcpu_clear_mmio_info(vcpu, MMIO_GVA_ANY);
__clear_sp_write_flooding_count( __clear_sp_write_flooding_count(page_header(vcpu->arch.mmu->root_hpa));
page_header(mmu->root_hpa));
return true;
}
}
return false;
}
static void __kvm_mmu_new_cr3(struct kvm_vcpu *vcpu, gpa_t new_cr3,
union kvm_mmu_page_role new_role,
bool skip_tlb_flush)
{
if (!fast_cr3_switch(vcpu, new_cr3, new_role, skip_tlb_flush))
kvm_mmu_free_roots(vcpu, vcpu->arch.mmu,
KVM_MMU_ROOT_CURRENT);
} }
void kvm_mmu_new_cr3(struct kvm_vcpu *vcpu, gpa_t new_cr3, bool skip_tlb_flush) void kvm_mmu_new_cr3(struct kvm_vcpu *vcpu, gpa_t new_cr3, bool skip_tlb_flush)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment