Re: [PATCH v4 18/18] KVM: guest_memfd: Combine .gmem_prepare()+.gmem_invalidate() into .gmem_convert()
From: Sean Christopherson
Date: Tue Jul 21 2026 - 16:37:16 EST
On Wed, Jul 15, 2026, Yan Zhao wrote:
> > @@ -802,7 +801,7 @@ int kvm_gmem_get_pfn(struct kvm *kvm, struct kvm_memory_slot *slot,
> > folio_mark_uptodate(folio);
> > }
> >
> > - r = kvm_gmem_prepare_folio(kvm, slot, gfn, folio);
> > + r = kvm_gmem_make_private(kvm, slot, gfn, folio);
> What puzzles me is that kvm_gmem_get_pfn() can be invoked to fault in pages for
> gmem-only slots in normal VMs, where kvm_arch_has_private_mem() == false.
>
> Would it be odd to invoke .gmem_convert() with to_private being true in such
> VMs? Or do you plan to add something similar to the following in the future?
> if (kvm_gmem_is_private_mem(inode, index))
> r = kvm_gmem_make_private(kvm, slot, gfn, folio);
> else
> r = kvm_gmem_make_shared(kvm, slot, gfn, folio);
>
> Otherwise, would it look asymmetric with just:
> if (kvm_gmem_is_private_mem(inode, index))
> r = kvm_gmem_make_private(kvm, slot, gfn, folio);
> in kvm_gmem_get_pfn()?
Heh, I should have read this sooner. With help from Xiaoyao and Ackerley, I
eventually got to the same place.
https://lore.kernel.org/all/al-aDRTbDOPT1UbM@xxxxxxxxxx
> Asking this also because there is a .gmem_convert() for TDX huge pages [1].
> In [1], .gmem_convert() is invoked to emulate a to-shared conversion in
> kvm_gmem_punch_hole(). However, the per-gmem memory attribute for the range to
> convert may not be shared after the punch hole. Is it acceptable?
> (To me, the .gmem_convert() in [1] behaves more like .gmem_prezap()).
Ya, these concerns got raised by others. pKVM on arm64 in particular wants to
hook reclaim but not conversion. The plan is to keep the reclaim and end up with
this implementation for x86:
#ifdef CONFIG_HAVE_KVM_ARCH_GMEM_CONVERT
int kvm_arch_gmem_make_private(struct kvm *kvm, gfn_t gfn, kvm_pfn_t pfn,
kvm_pfn_t nr_pages, int max_order)
{
return kvm_x86_call(gmem_make_private)(kvm, gfn, pfn, nr_pages, max_order);
}
int kvm_arch_gmem_make_shared(kvm_pfn_t pfn, kvm_pfn_t nr_pages, int max_order,
bool to_private)
{
kvm_x86_call(gmem_make_shared)(pfn, nr_pages, max_order);
return 0;
}
#endif
#ifdef CONFIG_HAVE_KVM_ARCH_GMEM_RECLAIM
void kvm_arch_gmem_reclaim(kvm_pfn_t pfn, kvm_pfn_t nr_pages, int max_order)
{
kvm_x86_call(gmem_make_shared)(pfn, nr_pages, max_order);
}
#endif