Re: [PATCH] KVM: SEV: drop FOLL_LONGTERM for encrypted region registration

From: Sean Christopherson

Date: Wed Jul 01 2026 - 12:52:12 EST


On Wed, Jul 01, 2026, David Hildenbrand (Arm) wrote:
> On 7/1/26 16:45, Pankaj Gupta wrote:
> > commit 7e066cb9b71a ("KVM: SEV: Use long-term pin when registering encrypted memory regions")
> > added FOLL_LONGTERM to sev_mem_enc_register_region() so anonymous guest RAM is
> > migrated out of MIGRATE_CMA/ZONE_MOVABLE before a long term pin. This breaks
> > virtio-pmem which has file backed (MAP_SHARED) host mapping where GUP rejects
> > FOLL_WRITE | FOLL_LONGTERM since:
> >
> > commit 8ac268436e6d ("mm/gup: disallow FOLL_LONGTERM GUP-nonfast writing to file-backed mappings")
> > commit a6e79df92e4a ("mm/gup: disallow FOLL_LONGTERM GUP-fast writing to file-backed mappings").
> >
> > Drop FOLL_LONGTERM when registering encrypted memory regions and restore
> > the previous behavior.
>
> But that breaks the original issue of breaking ZONE_MOVABLE/CMA?

Ya.

> If it is a longterm pin, it must use FOLL_LONGTERM. :/

Heh, well, KVM showed that that's not entirely true for many years :-)

Assuming we can't solve this some other way, and that there are "real" use cases
that were broken by adding FOLL_LONGTERM, maybe this as a hack-a-fix?

diff --git a/arch/x86/kvm/svm/sev.c b/arch/x86/kvm/svm/sev.c
index 74fb15551e83..ea136d79c963 100644
--- a/arch/x86/kvm/svm/sev.c
+++ b/arch/x86/kvm/svm/sev.c
@@ -2752,6 +2752,25 @@ int sev_mem_enc_register_region(struct kvm *kvm,

region->pages = sev_pin_memory(kvm, range->addr, range->size, &region->npages,
FOLL_WRITE | FOLL_LONGTERM);
+
+ /*
+ * On failure, attempt a "short"-term pin for backwards compatibility,
+ * in quotes because this isn't actually a short-term pin. The kernel
+ * disallows long-term writable pins on file-backed memory as a partial
+ * defense against the fundamental problem that most filesystems don't
+ * play nice with kernel writes via GUP (true short-term pins are much
+ * less likely to be problematic).
+ *
+ * Unfortunately, KVM (incorrectly) used a short-term pin for years,
+ * and so can't *require* a long-term pin. And for this use case, the
+ * potential filesystem crashes that occur with kernel writes are a
+ * non-issue, as KVM isn't using this pin to access guest memory, the
+ * pin is performed purely to prevent the memory from being migrated.
+ */
+ if (IS_ERR(region->pages))
+ region->pages = sev_pin_memory(kvm, range->addr, range->size,
+ &region->npages, FOLL_WRITE);
+
if (IS_ERR(region->pages)) {
ret = PTR_ERR(region->pages);
goto e_free;

> I assume we fail in check_vma_flags()
>
> if ((gup_flags & FOLL_LONGTERM) && vma_is_fsdax(vma))
> return -EOPNOTSUPP;
>
> IIRC, fsdax cannot tolerate unbounded pins. Is that the case we are running into?
>
> How does vfio deal with that? (does it?)
>
> --
> Cheers,
>
> David