Re: [PATCH v2 4/9] KVM: Rework .gmem_invalidate() into .gmem_free_folio()
From: Sean Christopherson
Date: Mon Jun 29 2026 - 18:02:38 EST
On Mon, Jun 29, 2026, Ackerley Tng wrote:
> Sean Christopherson <seanjc@xxxxxxxxxx> writes:
>
> >
> > [...snip...]
> >
> >
> > -void sev_gmem_invalidate(kvm_pfn_t start, kvm_pfn_t end)
> > +void sev_gmem_free_folio(struct folio *folio)
> > {
> > + kvm_pfn_t start = page_to_pfn(folio_page(folio, 0));
> > + kvm_pfn_t end = start + (1ul << folio_order(folio));
> > kvm_pfn_t pfn;
> >
> > if (!cc_platform_has(CC_ATTR_HOST_SEV_SNP))
>
> I thought we intended to draw the line such that the platforms don't
> reference folios, and so this function should be parametrized by pfn.
>
> I think we should still stick with
>
> .free_folio = kvm_gmem_free_folio
>
> and kvm_gmem_free_folio() translates the folio to pfns and calls the
> arch function, named something like .gmem_LIFECYCLE_ACTION_pfn_range.
>
> Now for LIFECYCLE_ACTION, one way to think of it is that this should
> represent the point in the lifecycle of guest_memfd memory where the
> memory is removed from guest's private use, so perhaps "host_reclaim"?
kvm_arch_gmem_reclaim_memory()? I don't want to include "host", because the
"reclaim" may or may not be host initiated. I don't want to use "pfn_range"
because it's too close to "gfn_range".
> Then kvm_gmem_free_folio() becomes:
>
> kvm_gmem_free_folio() {
> pfn_start, pfn_end = translate folio to pfn range;
> kvm_x86_call(gmem_host_reclaim_pfn_range)(pfn_start, pfn_end);
> }
>
>
> And in conversions
>
> if (!to_private) {
> pfn_start, pfn_end = translate guest_memfd offset range to pfns;
> kvm_x86_call(gmem_host_reclaim_pfn_range)(pfn_start, pfn_end);
> }
>
> (and now it is right for the !to_private check to remain in guest_memfd
> since we're explicitly using that to guard a *host* reclaim function.
>
> Another way to think of LIFECYCLE_ACTION is to have the hook represent
> the point of time where the memory's attribute is being set. Perhaps
> "set_attributes"?
>
> Then kvm_gmem_free_folio() becomes:
>
> kvm_gmem_free_folio() {
> pfn_start, pfn_end = translate folio to pfn range;
> kvm_x86_call(gmem_set_attributes_pfn_range)(pfn_start, pfn_end, SHARED);
No, because this isn't about setting memory PRIVATE vs. SHARED, it's about freeing
memory back to the host. Which is why I suggested the comically verbose
CONFIG_KVM_ARCH_GMEM_FREE_ON_SHARED_CONVERSION: SEV-SNP effectively frees memory
when converting to shared.
> }
>
> because when freeing a folio we want to set the attributes to SHARED.
No, because the RMP isn't being moved to a "shared" state per se, rather the page
is being unassigned. And from KVM's perspective, freeing the folio can happen
even if the memory isn't first converted to SHARED (in KVM's memory attributes).
> And in conversions
>
> if (kvm_x86_call(gmem_should_set_attributes_pfn_range)(SHARED)) {
> pfn_start, pfn_end = translate guest_memfd offset range to pfns;
> kvm_x86_call(gmem_set_attributes_pfn_range)(pfn_start, pfn_end, SHARED);
> }
>
> This is biased towards conversions (related proposal at [1]).
>
> [1] https://lore.kernel.org/all/CAEvNRgGX3GkazCWM=6y9YLgn=YemXuG==Oo+L58cac1Fd86_TQ@xxxxxxxxxxxxxx/
>
> >
> > [...snip...]
> >