Re: [PATCH v5 2/7] KVM: guest_memfd: Rename invalidate() arch hook to reclaim() and isolate it
From: Fuad Tabba
Date: Wed Jul 15 2026 - 04:21:11 EST
On Wed, 15 Jul 2026 at 00:10, Sean Christopherson <seanjc@xxxxxxxxxx> wrote:
>
> Rename guest_memfd's invalidate() hook to reclaim() and isolate it via its
> own RECLAIM Kconfig, as the hook is called when a folio is freed, which is
> far too late and lacks sufficient information for KVM to actually
> invalidate its usage of the memory. E.g. SNP uses the hook to convert
> memory back to SHARED so that it can be safely accessed by the host, there
> is no invalidation of guest mappings anywhere. Isolating the hook will
> also allow pKVM on arm64 to opt-in to reclaim() without also having to
> differentiate between reclaim and conversions to shared for active VMs.
>
> Keep guest_memfd's trampoline, even though it would be trivial to wire up
> .free_folio() directly to an arch callback, to avoid bleeding guest_memfd
> internals into arch code (specifically, avoid referencing folios in arch
> code).
>
> Leave the kvm_x86_ops hook as-is for the moment, as the hook can be dropped
> entirely ("reclaim" on SNP is the same as convert-to-shared).
>
> Cc: Fuad Tabba <tabba@xxxxxxxxxx>
> Cc: Ackerley Tng <ackerleytng@xxxxxxxxxx>
> Signed-off-by: Sean Christopherson <seanjc@xxxxxxxxxx>
Thanks Sean, this matches what pKVM needs: we'll select
HAVE_KVM_ARCH_GMEM_RECLAIM and implement kvm_arch_gmem_reclaim() only,
without the convert hook, so teardown (which for pKVM must scrub the
page before it returns to the host) stays distinct from a
private->shared conversion (which must preserve it).
Same nit as patch 1 (order/max_order).
Reviewed-by: Fuad Tabba <fuad.tabba@xxxxxxxxx>
Cheers,
/fuad
> ---
> arch/x86/kvm/Kconfig | 1 +
> arch/x86/kvm/x86.c | 7 +++++--
> include/linux/kvm_host.h | 5 ++++-
> virt/kvm/Kconfig | 4 ++++
> virt/kvm/guest_memfd.c | 8 ++++----
> 5 files changed, 18 insertions(+), 7 deletions(-)
>
> diff --git a/arch/x86/kvm/Kconfig b/arch/x86/kvm/Kconfig
> index 801bf9e520db..e0e7ad015839 100644
> --- a/arch/x86/kvm/Kconfig
> +++ b/arch/x86/kvm/Kconfig
> @@ -161,6 +161,7 @@ config KVM_AMD_SEV
> select ARCH_HAS_CC_PLATFORM
> select KVM_GENERIC_MEMORY_ATTRIBUTES
> select HAVE_KVM_ARCH_GMEM_PREPARE
> + select HAVE_KVM_ARCH_GMEM_RECLAIM
> select HAVE_KVM_ARCH_GMEM_INVALIDATE
> select HAVE_KVM_ARCH_GMEM_POPULATE
> help
> diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
> index a2cbf6fae118..08d24c6fffa4 100644
> --- a/arch/x86/kvm/x86.c
> +++ b/arch/x86/kvm/x86.c
> @@ -10626,11 +10626,14 @@ int kvm_arch_gmem_prepare(struct kvm *kvm, gfn_t gfn, kvm_pfn_t pfn, int max_ord
> }
> #endif
>
> -#ifdef CONFIG_HAVE_KVM_ARCH_GMEM_INVALIDATE
> -void kvm_arch_gmem_invalidate(kvm_pfn_t pfn, kvm_pfn_t nr_pages, int max_order)
> +#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_invalidate)(pfn, pfn + nr_pages);
> }
> +#endif
> +
> +#ifdef CONFIG_HAVE_KVM_ARCH_GMEM_INVALIDATE
> void kvm_arch_gmem_invalidate_range(struct kvm *kvm, struct kvm_gfn_range *range)
> {
> kvm_x86_call(gmem_invalidate_range)(kvm, range);
> diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
> index 996b39ebdb68..ee87ddd3294f 100644
> --- a/include/linux/kvm_host.h
> +++ b/include/linux/kvm_host.h
> @@ -2613,8 +2613,11 @@ long kvm_gmem_populate(struct kvm *kvm, gfn_t start_gfn, void __user *src,
> kvm_gmem_populate_cb post_populate, void *opaque);
> #endif
>
> +#ifdef CONFIG_HAVE_KVM_ARCH_GMEM_RECLAIM
> +void kvm_arch_gmem_reclaim(kvm_pfn_t pfn, kvm_pfn_t nr_pages, int order);
> +#endif
> +
> #ifdef CONFIG_HAVE_KVM_ARCH_GMEM_INVALIDATE
> -void kvm_arch_gmem_invalidate(kvm_pfn_t pfn, kvm_pfn_t nr_pages, int order);
> void kvm_arch_gmem_invalidate_range(struct kvm *kvm, struct kvm_gfn_range *range);
> #endif
>
> diff --git a/virt/kvm/Kconfig b/virt/kvm/Kconfig
> index 794976b88c6f..617876993225 100644
> --- a/virt/kvm/Kconfig
> +++ b/virt/kvm/Kconfig
> @@ -111,6 +111,10 @@ config HAVE_KVM_ARCH_GMEM_PREPARE
> bool
> depends on KVM_GUEST_MEMFD
>
> +config HAVE_KVM_ARCH_GMEM_RECLAIM
> + bool
> + depends on KVM_GUEST_MEMFD
> +
> config HAVE_KVM_ARCH_GMEM_INVALIDATE
> bool
> depends on KVM_GUEST_MEMFD
> diff --git a/virt/kvm/guest_memfd.c b/virt/kvm/guest_memfd.c
> index 99c070bfd446..d5d227476cda 100644
> --- a/virt/kvm/guest_memfd.c
> +++ b/virt/kvm/guest_memfd.c
> @@ -527,11 +527,11 @@ static int kvm_gmem_error_folio(struct address_space *mapping, struct folio *fol
> return MF_DELAYED;
> }
>
> -#ifdef CONFIG_HAVE_KVM_ARCH_GMEM_INVALIDATE
> +#ifdef CONFIG_HAVE_KVM_ARCH_GMEM_RECLAIM
> static void kvm_gmem_free_folio(struct folio *folio)
> {
> - kvm_arch_gmem_invalidate(folio_file_pfn(folio, 0), folio_nr_pages(folio),
> - folio_order(folio));
> + kvm_arch_gmem_reclaim(folio_file_pfn(folio, 0), folio_nr_pages(folio),
> + folio_order(folio));
> }
> #endif
>
> @@ -539,7 +539,7 @@ static const struct address_space_operations kvm_gmem_aops = {
> .dirty_folio = noop_dirty_folio,
> .migrate_folio = kvm_gmem_migrate_folio,
> .error_remove_folio = kvm_gmem_error_folio,
> -#ifdef CONFIG_HAVE_KVM_ARCH_GMEM_INVALIDATE
> +#ifdef CONFIG_HAVE_KVM_ARCH_GMEM_RECLAIM
> .free_folio = kvm_gmem_free_folio,
> #endif
> };
> --
> 2.55.0.141.g00534a21ce-goog
>