| From f3af5f79fad6db6fa6dd1181cced3bff83cbd747 Mon Sep 17 00:00:00 2001 |
| From: David Stevens <stevensd@chromium.org> |
| Date: Fri, 25 Jun 2021 16:36:14 +0900 |
| Subject: [PATCH] BACKPORT: FROMLIST: KVM: x86/mmu: use gfn_to_pfn_page |
| |
| Covert usages of the deprecated gfn_to_pfn functions to the new |
| gfn_to_pfn_page functions. |
| |
| Signed-off-by: David Stevens <stevensd@chromium.org> |
| (am from https://lore.kernel.org/patchwork/patch/1451586/) |
| (also found at https://lore.kernel.org/r/20210625073616.2184426-4-stevensd@google.com) |
| |
| Conflicts: |
| arch/x86/kvm/mmu/mmu.c |
| arch/x86/kvm/mmu/paging_tmpl.h |
| arch/x86/kvm/mmu/tdp_mmu.c |
| |
| BUG=b:184929592, b:176387875 |
| TEST=tast run zork arc.VideoDecodeAccel.vp9_vm |
| |
| Change-Id: Ibc1ac43303a26cd78dc442a793691c15728b789b |
| Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/third_party/kernel/+/3002593 |
| Tested-by: David Stevens <stevensd@chromium.org> |
| Reviewed-by: Suleiman Souhlal <suleiman@chromium.org> |
| Commit-Queue: David Stevens <stevensd@chromium.org> |
| --- |
| arch/x86/kvm/mmu/mmu.c | 41 ++++++++++++++++++++------------- |
| arch/x86/kvm/mmu/mmu_internal.h | 3 ++- |
| arch/x86/kvm/mmu/paging_tmpl.h | 23 ++++++++++-------- |
| arch/x86/kvm/mmu/tdp_mmu.c | 6 ++--- |
| arch/x86/kvm/mmu/tdp_mmu.h | 4 ++-- |
| arch/x86/kvm/x86.c | 6 +++-- |
| 6 files changed, 50 insertions(+), 33 deletions(-) |
| |
| diff --git a/arch/x86/kvm/mmu/mmu.c b/arch/x86/kvm/mmu/mmu.c |
| --- a/arch/x86/kvm/mmu/mmu.c |
| +++ b/arch/x86/kvm/mmu/mmu.c |
| @@ -2783,8 +2783,9 @@ static int mmu_set_spte(struct kvm_vcpu *vcpu, u64 *sptep, |
| return ret; |
| } |
| |
| -static kvm_pfn_t pte_prefetch_gfn_to_pfn(struct kvm_vcpu *vcpu, gfn_t gfn, |
| - bool no_dirty_log) |
| +static kvm_pfn_t pte_prefetch_gfn_to_pfn_page(struct kvm_vcpu *vcpu, |
| + gfn_t gfn, bool no_dirty_log, |
| + struct page **page) |
| { |
| struct kvm_memory_slot *slot; |
| |
| @@ -2792,7 +2793,7 @@ static kvm_pfn_t pte_prefetch_gfn_to_pfn(struct kvm_vcpu *vcpu, gfn_t gfn, |
| if (!slot) |
| return KVM_PFN_ERR_FAULT; |
| |
| - return gfn_to_pfn_memslot_atomic(slot, gfn); |
| + return gfn_to_pfn_page_memslot_atomic(slot, gfn, page); |
| } |
| |
| static int direct_pte_prefetch_many(struct kvm_vcpu *vcpu, |
| @@ -2923,7 +2924,8 @@ int kvm_mmu_max_mapping_level(struct kvm *kvm, |
| |
| int kvm_mmu_hugepage_adjust(struct kvm_vcpu *vcpu, gfn_t gfn, |
| int max_level, kvm_pfn_t *pfnp, |
| - bool huge_page_disallowed, int *req_level) |
| + struct page *page, bool huge_page_disallowed, |
| + int *req_level) |
| { |
| struct kvm_memory_slot *slot; |
| kvm_pfn_t pfn = *pfnp; |
| @@ -2935,6 +2937,9 @@ int kvm_mmu_hugepage_adjust(struct kvm_vcpu *vcpu, gfn_t gfn, |
| if (unlikely(max_level == PG_LEVEL_4K)) |
| return PG_LEVEL_4K; |
| |
| + if (!page) |
| + return PG_LEVEL_4K; |
| + |
| if (is_error_noslot_pfn(pfn) || kvm_is_reserved_pfn(pfn)) |
| return PG_LEVEL_4K; |
| |
| @@ -2984,7 +2989,8 @@ void disallowed_hugepage_adjust(u64 spte, gfn_t gfn, int cur_level, |
| } |
| |
| static int __direct_map(struct kvm_vcpu *vcpu, gpa_t gpa, u32 error_code, |
| - int map_writable, int max_level, kvm_pfn_t pfn, |
| + int map_writable, int max_level, |
| + kvm_pfn_t pfn, struct page *page, |
| bool prefault, bool is_tdp) |
| { |
| bool nx_huge_page_workaround_enabled = is_nx_huge_page_enabled(); |
| @@ -2997,7 +3003,7 @@ static int __direct_map(struct kvm_vcpu *vcpu, gpa_t gpa, u32 error_code, |
| gfn_t gfn = gpa >> PAGE_SHIFT; |
| gfn_t base_gfn = gfn; |
| |
| - level = kvm_mmu_hugepage_adjust(vcpu, gfn, max_level, &pfn, |
| + level = kvm_mmu_hugepage_adjust(vcpu, gfn, max_level, &pfn, page, |
| huge_page_disallowed, &req_level); |
| |
| trace_kvm_mmu_spte_requested(gpa, level, pfn); |
| @@ -3902,7 +3908,8 @@ static bool kvm_arch_setup_async_pf(struct kvm_vcpu *vcpu, gpa_t cr2_or_gpa, |
| |
| static bool kvm_faultin_pfn(struct kvm_vcpu *vcpu, bool prefault, gfn_t gfn, |
| gpa_t cr2_or_gpa, kvm_pfn_t *pfn, hva_t *hva, |
| - bool write, bool *writable, int *r) |
| + bool write, bool *writable, int *r, |
| + struct page **page) |
| { |
| struct kvm_memory_slot *slot = kvm_vcpu_gfn_to_memslot(vcpu, gfn); |
| bool async; |
| @@ -3936,8 +3943,8 @@ static bool kvm_faultin_pfn(struct kvm_vcpu *vcpu, bool prefault, gfn_t gfn, |
| } |
| |
| async = false; |
| - *pfn = __gfn_to_pfn_memslot(slot, gfn, false, &async, |
| - write, writable, hva); |
| + *pfn = __gfn_to_pfn_page_memslot(slot, gfn, false, &async, |
| + write, writable, hva, page); |
| if (!async) |
| return false; /* *pfn has correct page already */ |
| |
| @@ -3951,8 +3958,8 @@ static bool kvm_faultin_pfn(struct kvm_vcpu *vcpu, bool prefault, gfn_t gfn, |
| goto out_retry; |
| } |
| |
| - *pfn = __gfn_to_pfn_memslot(slot, gfn, false, NULL, |
| - write, writable, hva); |
| + *pfn = __gfn_to_pfn_page_memslot(slot, gfn, false, NULL, |
| + write, writable, hva, page); |
| |
| out_retry: |
| *r = RET_PF_RETRY; |
| @@ -3969,6 +3976,7 @@ static int direct_page_fault(struct kvm_vcpu *vcpu, gpa_t gpa, u32 error_code, |
| gfn_t gfn = gpa >> PAGE_SHIFT; |
| unsigned long mmu_seq; |
| kvm_pfn_t pfn; |
| + struct page *page; |
| hva_t hva; |
| int r; |
| |
| @@ -3987,7 +3995,7 @@ static int direct_page_fault(struct kvm_vcpu *vcpu, gpa_t gpa, u32 error_code, |
| smp_rmb(); |
| |
| if (kvm_faultin_pfn(vcpu, prefault, gfn, gpa, &pfn, &hva, |
| - write, &map_writable, &r)) |
| + write, &map_writable, &r, &page)) |
| return r; |
| |
| if (handle_abnormal_pfn(vcpu, is_tdp ? 0 : gpa, gfn, pfn, ACC_ALL, &r)) |
| @@ -4008,17 +4016,18 @@ static int direct_page_fault(struct kvm_vcpu *vcpu, gpa_t gpa, u32 error_code, |
| |
| if (is_tdp_mmu_fault) |
| r = kvm_tdp_mmu_map(vcpu, gpa, error_code, map_writable, max_level, |
| - pfn, prefault); |
| + pfn, page, prefault); |
| else |
| - r = __direct_map(vcpu, gpa, error_code, map_writable, max_level, pfn, |
| - prefault, is_tdp); |
| + r = __direct_map(vcpu, gpa, error_code, map_writable, max_level, |
| + pfn, page, prefault, is_tdp); |
| |
| out_unlock: |
| if (is_tdp_mmu_fault) |
| read_unlock(&vcpu->kvm->mmu_lock); |
| else |
| write_unlock(&vcpu->kvm->mmu_lock); |
| - kvm_release_pfn_clean(pfn); |
| + if (page) |
| + put_page(page); |
| return r; |
| } |
| |
| diff --git a/arch/x86/kvm/mmu/mmu_internal.h b/arch/x86/kvm/mmu/mmu_internal.h |
| --- a/arch/x86/kvm/mmu/mmu_internal.h |
| +++ b/arch/x86/kvm/mmu/mmu_internal.h |
| @@ -165,7 +165,8 @@ int kvm_mmu_max_mapping_level(struct kvm *kvm, |
| kvm_pfn_t pfn, int max_level); |
| int kvm_mmu_hugepage_adjust(struct kvm_vcpu *vcpu, gfn_t gfn, |
| int max_level, kvm_pfn_t *pfnp, |
| - bool huge_page_disallowed, int *req_level); |
| + struct page *page, bool huge_page_disallowed, |
| + int *req_level); |
| void disallowed_hugepage_adjust(u64 spte, gfn_t gfn, int cur_level, |
| kvm_pfn_t *pfnp, int *goal_levelp); |
| |
| diff --git a/arch/x86/kvm/mmu/paging_tmpl.h b/arch/x86/kvm/mmu/paging_tmpl.h |
| --- a/arch/x86/kvm/mmu/paging_tmpl.h |
| +++ b/arch/x86/kvm/mmu/paging_tmpl.h |
| @@ -564,6 +564,7 @@ FNAME(prefetch_gpte)(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp, |
| unsigned pte_access; |
| gfn_t gfn; |
| kvm_pfn_t pfn; |
| + struct page *page; |
| |
| if (FNAME(prefetch_invalid_gpte)(vcpu, sp, spte, gpte)) |
| return false; |
| @@ -573,8 +574,8 @@ FNAME(prefetch_gpte)(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp, |
| gfn = gpte_to_gfn(gpte); |
| pte_access = sp->role.access & FNAME(gpte_access)(gpte); |
| FNAME(protect_clean_gpte)(vcpu->arch.mmu, &pte_access, gpte); |
| - pfn = pte_prefetch_gfn_to_pfn(vcpu, gfn, |
| - no_dirty_log && (pte_access & ACC_WRITE_MASK)); |
| + pfn = pte_prefetch_gfn_to_pfn_page(vcpu, gfn, |
| + no_dirty_log && (pte_access & ACC_WRITE_MASK), &page); |
| if (is_error_pfn(pfn)) |
| return false; |
| |
| @@ -585,7 +586,8 @@ FNAME(prefetch_gpte)(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp, |
| mmu_set_spte(vcpu, spte, pte_access, false, PG_LEVEL_4K, gfn, pfn, |
| true, true); |
| |
| - kvm_release_pfn_clean(pfn); |
| + if (page) |
| + put_page(page); |
| return true; |
| } |
| |
| @@ -665,8 +667,8 @@ static void FNAME(pte_prefetch)(struct kvm_vcpu *vcpu, struct guest_walker *gw, |
| */ |
| static int FNAME(fetch)(struct kvm_vcpu *vcpu, gpa_t addr, |
| struct guest_walker *gw, u32 error_code, |
| - int max_level, kvm_pfn_t pfn, bool map_writable, |
| - bool prefault) |
| + int max_level, kvm_pfn_t pfn, struct page *page, |
| + bool map_writable, bool prefault) |
| { |
| bool nx_huge_page_workaround_enabled = is_nx_huge_page_enabled(); |
| bool write_fault = error_code & PFERR_WRITE_MASK; |
| @@ -723,7 +725,8 @@ static int FNAME(fetch)(struct kvm_vcpu *vcpu, gpa_t addr, |
| } |
| |
| level = kvm_mmu_hugepage_adjust(vcpu, gw->gfn, max_level, &pfn, |
| - huge_page_disallowed, &req_level); |
| + page, huge_page_disallowed, |
| + &req_level); |
| |
| trace_kvm_mmu_spte_requested(addr, gw->level, pfn); |
| |
| @@ -830,6 +833,7 @@ static int FNAME(page_fault)(struct kvm_vcpu *vcpu, gpa_t addr, u32 error_code, |
| struct guest_walker walker; |
| int r; |
| kvm_pfn_t pfn; |
| + struct page *page; |
| hva_t hva; |
| unsigned long mmu_seq; |
| bool map_writable, is_self_change_mapping; |
| @@ -882,7 +886,7 @@ static int FNAME(page_fault)(struct kvm_vcpu *vcpu, gpa_t addr, u32 error_code, |
| smp_rmb(); |
| |
| if (kvm_faultin_pfn(vcpu, prefault, walker.gfn, addr, &pfn, &hva, |
| - write_fault, &map_writable, &r)) |
| + write_fault, &map_writable, &r, &page)) |
| return r; |
| |
| if (handle_abnormal_pfn(vcpu, addr, walker.gfn, pfn, walker.pte_access, &r)) |
| @@ -916,13 +920,14 @@ static int FNAME(page_fault)(struct kvm_vcpu *vcpu, gpa_t addr, u32 error_code, |
| r = make_mmu_pages_available(vcpu); |
| if (r) |
| goto out_unlock; |
| - r = FNAME(fetch)(vcpu, addr, &walker, error_code, max_level, pfn, |
| + r = FNAME(fetch)(vcpu, addr, &walker, error_code, max_level, pfn, page, |
| map_writable, prefault); |
| kvm_mmu_audit(vcpu, AUDIT_POST_PAGE_FAULT); |
| |
| out_unlock: |
| write_unlock(&vcpu->kvm->mmu_lock); |
| - kvm_release_pfn_clean(pfn); |
| + if (page) |
| + put_page(page); |
| return r; |
| } |
| |
| diff --git a/arch/x86/kvm/mmu/tdp_mmu.c b/arch/x86/kvm/mmu/tdp_mmu.c |
| --- a/arch/x86/kvm/mmu/tdp_mmu.c |
| +++ b/arch/x86/kvm/mmu/tdp_mmu.c |
| @@ -987,8 +987,8 @@ static int tdp_mmu_map_handle_target_level(struct kvm_vcpu *vcpu, int write, |
| * page tables and SPTEs to translate the faulting guest physical address. |
| */ |
| int kvm_tdp_mmu_map(struct kvm_vcpu *vcpu, gpa_t gpa, u32 error_code, |
| - int map_writable, int max_level, kvm_pfn_t pfn, |
| - bool prefault) |
| + int map_writable, int max_level, |
| + kvm_pfn_t pfn, struct page *page, bool prefault) |
| { |
| bool nx_huge_page_workaround_enabled = is_nx_huge_page_enabled(); |
| bool write = error_code & PFERR_WRITE_MASK; |
| @@ -1004,7 +1004,7 @@ int kvm_tdp_mmu_map(struct kvm_vcpu *vcpu, gpa_t gpa, u32 error_code, |
| int level; |
| int req_level; |
| |
| - level = kvm_mmu_hugepage_adjust(vcpu, gfn, max_level, &pfn, |
| + level = kvm_mmu_hugepage_adjust(vcpu, gfn, max_level, &pfn, page, |
| huge_page_disallowed, &req_level); |
| |
| trace_kvm_mmu_spte_requested(gpa, level, pfn); |
| diff --git a/arch/x86/kvm/mmu/tdp_mmu.h b/arch/x86/kvm/mmu/tdp_mmu.h |
| --- a/arch/x86/kvm/mmu/tdp_mmu.h |
| +++ b/arch/x86/kvm/mmu/tdp_mmu.h |
| @@ -49,8 +49,8 @@ void kvm_tdp_mmu_invalidate_all_roots(struct kvm *kvm); |
| void kvm_tdp_mmu_zap_invalidated_roots(struct kvm *kvm); |
| |
| int kvm_tdp_mmu_map(struct kvm_vcpu *vcpu, gpa_t gpa, u32 error_code, |
| - int map_writable, int max_level, kvm_pfn_t pfn, |
| - bool prefault); |
| + int map_writable, int max_level, |
| + kvm_pfn_t pfn, struct page *page, bool prefault); |
| |
| bool kvm_tdp_mmu_unmap_gfn_range(struct kvm *kvm, struct kvm_gfn_range *range, |
| bool flush); |
| diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c |
| --- a/arch/x86/kvm/x86.c |
| +++ b/arch/x86/kvm/x86.c |
| @@ -7527,6 +7527,7 @@ static bool reexecute_instruction(struct kvm_vcpu *vcpu, gpa_t cr2_or_gpa, |
| { |
| gpa_t gpa = cr2_or_gpa; |
| kvm_pfn_t pfn; |
| + struct page *page; |
| |
| if (!(emulation_type & EMULTYPE_ALLOW_RETRY_PF)) |
| return false; |
| @@ -7556,7 +7557,7 @@ static bool reexecute_instruction(struct kvm_vcpu *vcpu, gpa_t cr2_or_gpa, |
| * retry instruction -> write #PF -> emulation fail -> retry |
| * instruction -> ... |
| */ |
| - pfn = gfn_to_pfn(vcpu->kvm, gpa_to_gfn(gpa)); |
| + pfn = gfn_to_pfn_page(vcpu->kvm, gpa_to_gfn(gpa), &page); |
| |
| /* |
| * If the instruction failed on the error pfn, it can not be fixed, |
| @@ -7565,7 +7566,8 @@ static bool reexecute_instruction(struct kvm_vcpu *vcpu, gpa_t cr2_or_gpa, |
| if (is_error_noslot_pfn(pfn)) |
| return false; |
| |
| - kvm_release_pfn_clean(pfn); |
| + if (page) |
| + put_page(page); |
| |
| /* The instructions are well-emulated on direct mmu. */ |
| if (vcpu->arch.mmu->direct_map) { |
| -- |
| 2.33.0.464.g1972c5931b-goog |
| |