138 lines
4.1 KiB
Diff
138 lines
4.1 KiB
Diff
From: Junaid Shahid <junaids@google.com>
|
|
Date: Thu, 3 Jan 2019 16:22:21 -0800
|
|
Subject: kvm: x86: Do not release the page inside mmu_set_spte()
|
|
|
|
commit 43fdcda96e2550c6d1c46fb8a78801aa2f7276ed upstream.
|
|
|
|
Release the page at the call-site where it was originally acquired.
|
|
This makes the exit code cleaner for most call sites, since they
|
|
do not need to duplicate code between success and the failure
|
|
label.
|
|
|
|
Signed-off-by: Junaid Shahid <junaids@google.com>
|
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
|
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
|
|
---
|
|
arch/x86/kvm/mmu.c | 18 +++++++-----------
|
|
arch/x86/kvm/paging_tmpl.h | 8 +++-----
|
|
2 files changed, 10 insertions(+), 16 deletions(-)
|
|
|
|
diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c
|
|
index c9d4e02bd73a..7dc18fb42168 100644
|
|
--- a/arch/x86/kvm/mmu.c
|
|
+++ b/arch/x86/kvm/mmu.c
|
|
@@ -3001,8 +3001,6 @@ static int mmu_set_spte(struct kvm_vcpu *vcpu, u64 *sptep, unsigned pte_access,
|
|
}
|
|
}
|
|
|
|
- kvm_release_pfn_clean(pfn);
|
|
-
|
|
return ret;
|
|
}
|
|
|
|
@@ -3037,9 +3035,11 @@ static int direct_pte_prefetch_many(struct kvm_vcpu *vcpu,
|
|
if (ret <= 0)
|
|
return -1;
|
|
|
|
- for (i = 0; i < ret; i++, gfn++, start++)
|
|
+ for (i = 0; i < ret; i++, gfn++, start++) {
|
|
mmu_set_spte(vcpu, start, access, 0, sp->role.level, gfn,
|
|
page_to_pfn(pages[i]), true, true);
|
|
+ put_page(pages[i]);
|
|
+ }
|
|
|
|
return 0;
|
|
}
|
|
@@ -3445,6 +3445,7 @@ static int nonpaging_map(struct kvm_vcpu *vcpu, gva_t v, u32 error_code,
|
|
if (handle_abnormal_pfn(vcpu, v, gfn, pfn, ACC_ALL, &r))
|
|
return r;
|
|
|
|
+ r = RET_PF_RETRY;
|
|
spin_lock(&vcpu->kvm->mmu_lock);
|
|
if (mmu_notifier_retry(vcpu->kvm, mmu_seq))
|
|
goto out_unlock;
|
|
@@ -3453,14 +3454,11 @@ static int nonpaging_map(struct kvm_vcpu *vcpu, gva_t v, u32 error_code,
|
|
if (likely(!force_pt_level))
|
|
transparent_hugepage_adjust(vcpu, &gfn, &pfn, &level);
|
|
r = __direct_map(vcpu, write, map_writable, level, gfn, pfn, prefault);
|
|
- spin_unlock(&vcpu->kvm->mmu_lock);
|
|
-
|
|
- return r;
|
|
|
|
out_unlock:
|
|
spin_unlock(&vcpu->kvm->mmu_lock);
|
|
kvm_release_pfn_clean(pfn);
|
|
- return RET_PF_RETRY;
|
|
+ return r;
|
|
}
|
|
|
|
static void mmu_free_root_page(struct kvm *kvm, hpa_t *root_hpa,
|
|
@@ -4082,6 +4080,7 @@ static int tdp_page_fault(struct kvm_vcpu *vcpu, gva_t gpa, u32 error_code,
|
|
if (handle_abnormal_pfn(vcpu, 0, gfn, pfn, ACC_ALL, &r))
|
|
return r;
|
|
|
|
+ r = RET_PF_RETRY;
|
|
spin_lock(&vcpu->kvm->mmu_lock);
|
|
if (mmu_notifier_retry(vcpu->kvm, mmu_seq))
|
|
goto out_unlock;
|
|
@@ -4090,14 +4089,11 @@ static int tdp_page_fault(struct kvm_vcpu *vcpu, gva_t gpa, u32 error_code,
|
|
if (likely(!force_pt_level))
|
|
transparent_hugepage_adjust(vcpu, &gfn, &pfn, &level);
|
|
r = __direct_map(vcpu, write, map_writable, level, gfn, pfn, prefault);
|
|
- spin_unlock(&vcpu->kvm->mmu_lock);
|
|
-
|
|
- return r;
|
|
|
|
out_unlock:
|
|
spin_unlock(&vcpu->kvm->mmu_lock);
|
|
kvm_release_pfn_clean(pfn);
|
|
- return RET_PF_RETRY;
|
|
+ return r;
|
|
}
|
|
|
|
static void nonpaging_init_context(struct kvm_vcpu *vcpu,
|
|
diff --git a/arch/x86/kvm/paging_tmpl.h b/arch/x86/kvm/paging_tmpl.h
|
|
index 14ffd973df54..569c55dae3fa 100644
|
|
--- a/arch/x86/kvm/paging_tmpl.h
|
|
+++ b/arch/x86/kvm/paging_tmpl.h
|
|
@@ -522,6 +522,7 @@ FNAME(prefetch_gpte)(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp,
|
|
mmu_set_spte(vcpu, spte, pte_access, 0, PT_PAGE_TABLE_LEVEL, gfn, pfn,
|
|
true, true);
|
|
|
|
+ kvm_release_pfn_clean(pfn);
|
|
return true;
|
|
}
|
|
|
|
@@ -673,7 +674,6 @@ static int FNAME(fetch)(struct kvm_vcpu *vcpu, gva_t addr,
|
|
return ret;
|
|
|
|
out_gpte_changed:
|
|
- kvm_release_pfn_clean(pfn);
|
|
return RET_PF_RETRY;
|
|
}
|
|
|
|
@@ -821,6 +821,7 @@ static int FNAME(page_fault)(struct kvm_vcpu *vcpu, gva_t addr, u32 error_code,
|
|
walker.pte_access &= ~ACC_EXEC_MASK;
|
|
}
|
|
|
|
+ r = RET_PF_RETRY;
|
|
spin_lock(&vcpu->kvm->mmu_lock);
|
|
if (mmu_notifier_retry(vcpu->kvm, mmu_seq))
|
|
goto out_unlock;
|
|
@@ -834,14 +835,11 @@ static int FNAME(page_fault)(struct kvm_vcpu *vcpu, gva_t addr, u32 error_code,
|
|
level, pfn, map_writable, prefault);
|
|
++vcpu->stat.pf_fixed;
|
|
kvm_mmu_audit(vcpu, AUDIT_POST_PAGE_FAULT);
|
|
- spin_unlock(&vcpu->kvm->mmu_lock);
|
|
-
|
|
- return r;
|
|
|
|
out_unlock:
|
|
spin_unlock(&vcpu->kvm->mmu_lock);
|
|
kvm_release_pfn_clean(pfn);
|
|
- return RET_PF_RETRY;
|
|
+ return r;
|
|
}
|
|
|
|
static gpa_t FNAME(get_level1_sp_gpa)(struct kvm_mmu_page *sp)
|