Skip to content

Commit ebf0027

Browse files
bibo-maochenhuacai
authored andcommitted
LoongArch: KVM: Mark page accessed and dirty with page ref added
Function kvm_map_page_fast() is fast path of secondary mmu page fault flow, pfn is parsed from secondary mmu page table walker. However the corresponding page reference is not added, it is dangerious to access page out of mmu_lock. Here page ref is added inside mmu_lock, function kvm_set_pfn_accessed() and kvm_set_pfn_dirty() is called with page ref added, so that the page will not be freed by others. Also kvm_set_pfn_accessed() is removed here since it is called in the following function kvm_release_pfn_clean(). Signed-off-by: Bibo Mao <[email protected]> Signed-off-by: Huacai Chen <[email protected]>
1 parent 8c34704 commit ebf0027

File tree

1 file changed

+13
-10
lines changed

1 file changed

+13
-10
lines changed

arch/loongarch/kvm/mmu.c

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -557,6 +557,7 @@ static int kvm_map_page_fast(struct kvm_vcpu *vcpu, unsigned long gpa, bool writ
557557
gfn_t gfn = gpa >> PAGE_SHIFT;
558558
struct kvm *kvm = vcpu->kvm;
559559
struct kvm_memory_slot *slot;
560+
struct page *page;
560561

561562
spin_lock(&kvm->mmu_lock);
562563

@@ -599,19 +600,22 @@ static int kvm_map_page_fast(struct kvm_vcpu *vcpu, unsigned long gpa, bool writ
599600
if (changed) {
600601
kvm_set_pte(ptep, new);
601602
pfn = kvm_pte_pfn(new);
603+
page = kvm_pfn_to_refcounted_page(pfn);
604+
if (page)
605+
get_page(page);
602606
}
603607
spin_unlock(&kvm->mmu_lock);
604608

605-
/*
606-
* Fixme: pfn may be freed after mmu_lock
607-
* kvm_try_get_pfn(pfn)/kvm_release_pfn pair to prevent this?
608-
*/
609-
if (kvm_pte_young(changed))
610-
kvm_set_pfn_accessed(pfn);
609+
if (changed) {
610+
if (kvm_pte_young(changed))
611+
kvm_set_pfn_accessed(pfn);
611612

612-
if (kvm_pte_dirty(changed)) {
613-
mark_page_dirty(kvm, gfn);
614-
kvm_set_pfn_dirty(pfn);
613+
if (kvm_pte_dirty(changed)) {
614+
mark_page_dirty(kvm, gfn);
615+
kvm_set_pfn_dirty(pfn);
616+
}
617+
if (page)
618+
put_page(page);
615619
}
616620
return ret;
617621
out:
@@ -920,7 +924,6 @@ static int kvm_map_page(struct kvm_vcpu *vcpu, unsigned long gpa, bool write)
920924
kvm_set_pfn_dirty(pfn);
921925
}
922926

923-
kvm_set_pfn_accessed(pfn);
924927
kvm_release_pfn_clean(pfn);
925928
out:
926929
srcu_read_unlock(&kvm->srcu, srcu_idx);

0 commit comments

Comments
 (0)