Commit 1affe455 authored by Yan Zhao's avatar Yan Zhao Committed by Sean Christopherson
Browse files

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: default avatarSean Christopherson <seanjc@google.com>
Signed-off-by: default avatarYan 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: default avatarSean Christopherson <seanjc@google.com>
parent 5804c19b
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -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);
+16 −9
Original line number Diff line number Diff line
@@ -4479,21 +4479,28 @@ static int kvm_tdp_mmu_page_fault(struct kvm_vcpu *vcpu,
}
#endif

int kvm_tdp_page_fault(struct kvm_vcpu *vcpu, struct kvm_page_fault *fault)
bool __kvm_mmu_honors_guest_mtrrs(bool vm_has_noncoherent_dma)
{
	/*
	 * 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.
	 * 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.
	 */
	if (shadow_memtype_mask && kvm_arch_has_noncoherent_dma(vcpu->kvm)) {
	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 (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,