diff --git a/arch/x86/kvm/mmu/mmu.c b/arch/x86/kvm/mmu/mmu.c index daf41806243f..7cfacfe8548e 100644 --- a/arch/x86/kvm/mmu/mmu.c +++ b/arch/x86/kvm/mmu/mmu.c @@ -1330,7 +1330,7 @@ gfn_to_memslot_dirty_bitmap(struct kvm_vcpu *vcpu, gfn_t gfn, static int mapping_level(struct kvm_vcpu *vcpu, gfn_t large_gfn, int *max_levelp) { - int host_level, max_level = *max_levelp; + int max_level = *max_levelp; struct kvm_memory_slot *slot; if (unlikely(max_level == PT_PAGE_TABLE_LEVEL)) @@ -1342,18 +1342,27 @@ static int mapping_level(struct kvm_vcpu *vcpu, gfn_t large_gfn, return PT_PAGE_TABLE_LEVEL; } - host_level = host_mapping_level(vcpu->kvm, large_gfn); - - if (host_level == PT_PAGE_TABLE_LEVEL) - return host_level; - - max_level = min(kvm_x86_ops->get_lpage_level(), host_level); + max_level = min(max_level, kvm_x86_ops->get_lpage_level()); for ( ; max_level > PT_PAGE_TABLE_LEVEL; max_level--) { if (!__mmu_gfn_lpage_is_disallowed(large_gfn, max_level, slot)) break; } - return max_level; + *max_levelp = max_level; + + if (max_level == PT_PAGE_TABLE_LEVEL) + return PT_PAGE_TABLE_LEVEL; + + /* + * Note, host_mapping_level() does *not* handle transparent huge pages. + * As suggested by "mapping", it reflects the page size established by + * the associated vma, if there is one, i.e. host_mapping_level() will + * return a huge page level if and only if a vma exists and the backing + * implementation for the vma uses huge pages, e.g. hugetlbfs and dax. + * So, do not propagate host_mapping_level() to max_level as KVM can + * still promote the guest mapping to a huge page in the THP case. + */ + return host_mapping_level(vcpu->kvm, large_gfn); } /* @@ -3424,8 +3433,7 @@ static void transparent_hugepage_adjust(struct kvm_vcpu *vcpu, */ if (!is_error_noslot_pfn(pfn) && !kvm_is_reserved_pfn(pfn) && !kvm_is_zone_device_pfn(pfn) && level == PT_PAGE_TABLE_LEVEL && - PageTransCompoundMap(pfn_to_page(pfn)) && - !mmu_gfn_lpage_is_disallowed(vcpu, gfn, PT_DIRECTORY_LEVEL)) { + PageTransCompoundMap(pfn_to_page(pfn))) { unsigned long mask; /* * mmu_notifier_retry was successful and we hold the