]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
KVM: PPC: Book3S: Mark "struct page" pfns dirty/accessed after installing PTE
authorSean Christopherson <seanjc@google.com>
Thu, 10 Oct 2024 18:24:05 +0000 (11:24 -0700)
committerPaolo Bonzini <pbonzini@redhat.com>
Fri, 25 Oct 2024 17:00:49 +0000 (13:00 -0400)
Mark pages/folios dirty/accessed after installing a PTE, and more
specifically after acquiring mmu_lock and checking for an mmu_notifier
invalidation.  Marking a page/folio dirty after it has been written back
can make some filesystems unhappy (backing KVM guests will such filesystem
files is uncommon, and the race is minuscule, hence the lack of complaints).
See the link below for details.

This will also allow converting Book3S to kvm_release_faultin_page(),
which requires that mmu_lock be held (for the aforementioned reason).

Link: https://lore.kernel.org/all/cover.1683044162.git.lstoakes@gmail.com
Signed-off-by: Sean Christopherson <seanjc@google.com>
Tested-by: Dmitry Osipenko <dmitry.osipenko@collabora.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Message-ID: <20241010182427.1434605-64-seanjc@google.com>

arch/powerpc/kvm/book3s_64_mmu_host.c

index bc6a381b53463795dbd7723a42bb13a6420566e4..d0e4f7bbdc3d833a4bd19833406d9e20c4d18761 100644 (file)
@@ -121,13 +121,10 @@ int kvmppc_mmu_map_page(struct kvm_vcpu *vcpu, struct kvmppc_pte *orig_pte,
 
        vpn = hpt_vpn(orig_pte->eaddr, map->host_vsid, MMU_SEGSIZE_256M);
 
-       kvm_set_pfn_accessed(pfn);
        if (!orig_pte->may_write || !writable)
                rflags |= PP_RXRX;
-       else {
+       else
                mark_page_dirty(vcpu->kvm, gfn);
-               kvm_set_pfn_dirty(pfn);
-       }
 
        if (!orig_pte->may_execute)
                rflags |= HPTE_R_N;
@@ -202,8 +199,11 @@ map_again:
        }
 
 out_unlock:
+       if (!orig_pte->may_write || !writable)
+               kvm_release_pfn_clean(pfn);
+       else
+               kvm_release_pfn_dirty(pfn);
        spin_unlock(&kvm->mmu_lock);
-       kvm_release_pfn_clean(pfn);
        if (cpte)
                kvmppc_mmu_hpte_cache_free(cpte);