Subject: kvm mmu transparent hugepage support From: Marcelo Tosatti This should work for both hugetlbfs and transparent hugepages. Signed-off-by: Andrea Arcangeli Signed-off-by: Marcelo Tosatti Acked-by: Rik van Riel --- diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c --- a/arch/x86/kvm/mmu.c +++ b/arch/x86/kvm/mmu.c @@ -471,6 +471,15 @@ static int host_mapping_level(struct kvm page_size = kvm_host_page_size(kvm, gfn); + /* check for transparent hugepages */ + if (page_size == PAGE_SIZE) { + struct page *page = gfn_to_page(kvm, gfn); + + if (!is_error_page(page) && PageTransCompound(page)) + page_size = KVM_HPAGE_SIZE(2); + kvm_release_page_clean(page); + } + for (i = PT_PAGE_TABLE_LEVEL; i < (PT_PAGE_TABLE_LEVEL + KVM_NR_PAGE_SIZES); ++i) { if (page_size >= KVM_HPAGE_SIZE(i)) @@ -1982,6 +1991,8 @@ static int nonpaging_map(struct kvm_vcpu pfn_t pfn; unsigned long mmu_seq; + mmu_seq = vcpu->kvm->mmu_notifier_seq; + smp_rmb(); level = mapping_level(vcpu, gfn); /* @@ -1993,8 +2004,6 @@ static int nonpaging_map(struct kvm_vcpu gfn &= ~(KVM_PAGES_PER_HPAGE(level) - 1); - mmu_seq = vcpu->kvm->mmu_notifier_seq; - smp_rmb(); pfn = gfn_to_pfn(vcpu->kvm, gfn); /* mmio */ @@ -2197,12 +2206,12 @@ static int tdp_page_fault(struct kvm_vcp if (r) return r; - level = mapping_level(vcpu, gfn); - - gfn &= ~(KVM_PAGES_PER_HPAGE(level) - 1); - mmu_seq = vcpu->kvm->mmu_notifier_seq; smp_rmb(); + level = mapping_level(vcpu, gfn); + + gfn &= ~(KVM_PAGES_PER_HPAGE(level) - 1); + pfn = gfn_to_pfn(vcpu->kvm, gfn); if (is_error_pfn(pfn)) { kvm_release_pfn_clean(pfn); diff --git a/arch/x86/kvm/paging_tmpl.h b/arch/x86/kvm/paging_tmpl.h --- a/arch/x86/kvm/paging_tmpl.h +++ b/arch/x86/kvm/paging_tmpl.h @@ -414,13 +414,13 @@ static int FNAME(page_fault)(struct kvm_ return 0; } + mmu_seq = vcpu->kvm->mmu_notifier_seq; + smp_rmb(); if (walker.level >= PT_DIRECTORY_LEVEL) { level = min(walker.level, mapping_level(vcpu, walker.gfn)); walker.gfn = walker.gfn & ~(KVM_PAGES_PER_HPAGE(level) - 1); } - mmu_seq = vcpu->kvm->mmu_notifier_seq; - smp_rmb(); pfn = gfn_to_pfn(vcpu->kvm, walker.gfn); /* mmio */