KVM: x86/mmu: Add helpers to return if KVM honors guest MTRRs
Add helpers to check if KVM honors guest MTRRs instead of open coding the logic in kvm_tdp_page_fault(). Future fixes and cleanups will also need to determine if KVM should honor guest MTRRs, e.g. for CR0.CD toggling and and non-coherent DMA transitions. Provide an inner helper, __kvm_mmu_honors_guest_mtrrs(), so that KVM can check if guest MTRRs were honored when stopping non-coherent DMA. Note, there is no need to explicitly check that TDP is enabled, KVM clears shadow_memtype_mask when TDP is disabled, i.e. it's non-zero if and only if EPT is enabled. Suggested-by: Sean Christopherson <seanjc@google.com> Signed-off-by: Yan Zhao <yan.y.zhao@intel.com> Link: https://lore.kernel.org/r/20230714065006.20201-1-yan.y.zhao@intel.com Link: https://lore.kernel.org/r/20230714065043.20258-1-yan.y.zhao@intel.com [sean: squash into a one patch, drop explicit TDP check massage changelog] Signed-off-by: Sean Christopherson <seanjc@google.com>
This commit is contained in:
parent
5804c19b80
commit
1affe455d6
@ -237,6 +237,13 @@ static inline u8 permission_fault(struct kvm_vcpu *vcpu, struct kvm_mmu *mmu,
|
||||
return -(u32)fault & errcode;
|
||||
}
|
||||
|
||||
bool __kvm_mmu_honors_guest_mtrrs(bool vm_has_noncoherent_dma);
|
||||
|
||||
static inline bool kvm_mmu_honors_guest_mtrrs(struct kvm *kvm)
|
||||
{
|
||||
return __kvm_mmu_honors_guest_mtrrs(kvm_arch_has_noncoherent_dma(kvm));
|
||||
}
|
||||
|
||||
void kvm_zap_gfn_range(struct kvm *kvm, gfn_t gfn_start, gfn_t gfn_end);
|
||||
|
||||
int kvm_arch_write_log_dirty(struct kvm_vcpu *vcpu);
|
||||
|
@ -4479,21 +4479,28 @@ out_unlock:
|
||||
}
|
||||
#endif
|
||||
|
||||
bool __kvm_mmu_honors_guest_mtrrs(bool vm_has_noncoherent_dma)
|
||||
{
|
||||
/*
|
||||
* If host MTRRs are ignored (shadow_memtype_mask is non-zero), and the
|
||||
* VM has non-coherent DMA (DMA doesn't snoop CPU caches), KVM's ABI is
|
||||
* to honor the memtype from the guest's MTRRs so that guest accesses
|
||||
* to memory that is DMA'd aren't cached against the guest's wishes.
|
||||
*
|
||||
* Note, KVM may still ultimately ignore guest MTRRs for certain PFNs,
|
||||
* e.g. KVM will force UC memtype for host MMIO.
|
||||
*/
|
||||
return vm_has_noncoherent_dma && shadow_memtype_mask;
|
||||
}
|
||||
|
||||
int kvm_tdp_page_fault(struct kvm_vcpu *vcpu, struct kvm_page_fault *fault)
|
||||
{
|
||||
/*
|
||||
* If the guest's MTRRs may be used to compute the "real" memtype,
|
||||
* restrict the mapping level to ensure KVM uses a consistent memtype
|
||||
* across the entire mapping. If the host MTRRs are ignored by TDP
|
||||
* (shadow_memtype_mask is non-zero), and the VM has non-coherent DMA
|
||||
* (DMA doesn't snoop CPU caches), KVM's ABI is to honor the memtype
|
||||
* from the guest's MTRRs so that guest accesses to memory that is
|
||||
* DMA'd aren't cached against the guest's wishes.
|
||||
*
|
||||
* Note, KVM may still ultimately ignore guest MTRRs for certain PFNs,
|
||||
* e.g. KVM will force UC memtype for host MMIO.
|
||||
* across the entire mapping.
|
||||
*/
|
||||
if (shadow_memtype_mask && kvm_arch_has_noncoherent_dma(vcpu->kvm)) {
|
||||
if (kvm_mmu_honors_guest_mtrrs(vcpu->kvm)) {
|
||||
for ( ; fault->max_level > PG_LEVEL_4K; --fault->max_level) {
|
||||
int page_num = KVM_PAGES_PER_HPAGE(fault->max_level);
|
||||
gfn_t base = gfn_round_for_level(fault->gfn,
|
||||
|
Loading…
x
Reference in New Issue
Block a user