From ee1a586dd1fa2f245b3b753a3e44d9263a49240b Mon Sep 17 00:00:00 2001 From: Pankaj Gupta Date: Wed, 15 Jul 2026 01:36:26 -0500 Subject: [PATCH] KVM: SEV: Drop FOLL_WRITE for encrypted region registration When pinning SEV guest memory, drop FOLL_WRITE and rely on FOLL_LONGTERM to break CoW, as *KVM* doesn't actually to the memory using the GUP'd pages. Omitting FOLL_WRITE fixes a regression when using file-backed guest memory that was introduced when KVM (correctly) added FOLL_LONG (e.g. to ensure anonymous memory is migrated out of MIGRATE_CMA/ZONE_MOVABLE before a long term pin). Unfortunately, as of commits: 8ac268436e6d ("mm/gup: disallow FOLL_LONGTERM GUP-nonfast writing to file-backed mappings") a6e79df92e4a ("mm/gup: disallow FOLL_LONGTERM GUP-fast writing to file-backed mappings") GUP uses FOLL_LONGTERM as a canary of sorts to detect pins that are likely to be problematic, and disallows WRITE+LONGTERM pins for file-backed memory. As a result, backing SEV+ guests with file-backed memory, e.g. virtio-pmem, fails due to the disallowed FOLL_LONGTERM+FOLL_WRITE combination. Note, in the past, FOLL_WRITE was required to trigger CoW unsharing, to prevent replacing the page in the (primary MMU's) page tables during a later write fault after already having pinned a (shared) page in MAP_PRIVATE mappings. FOLL_LONGTERM does that nowadays, even without FOLL_WRITE (see gup_must_unshare()). Fixes: 7e066cb9b71a ("KVM: SEV: Use long-term pin when registering encrypted memory regions") Cc: stable@vger.kernel.org Suggested-by: "David Hildenbrand (Arm)" Link: https://lore.kernel.org/all/ad784f05-b36c-4e91-9f17-4c5b826735d0@kernel.org/ Signed-off-by: Pankaj Gupta Acked-by: David Hildenbrand (Arm) Acked-by: Lorenzo Stoakes (ARM) Link: https://patch.msgid.link/20260715063626.65899-1-pankaj.gupta@amd.com [sean: massage changelog, add comment about CoW unsharing] Signed-off-by: Sean Christopherson --- arch/x86/kvm/svm/sev.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/arch/x86/kvm/svm/sev.c b/arch/x86/kvm/svm/sev.c index 74fb15551e83..91ffb2ae0fef 100644 --- a/arch/x86/kvm/svm/sev.c +++ b/arch/x86/kvm/svm/sev.c @@ -2750,8 +2750,12 @@ int sev_mem_enc_register_region(struct kvm *kvm, if (!region) return -ENOMEM; + /* + * Do NOT specify FOLL_WRITE, as KVM isn't using the pinned pages to + * write memory, and FOLL_LONGTERM itself triggers CoW unshare. + */ region->pages = sev_pin_memory(kvm, range->addr, range->size, ®ion->npages, - FOLL_WRITE | FOLL_LONGTERM); + FOLL_LONGTERM); if (IS_ERR(region->pages)) { ret = PTR_ERR(region->pages); goto e_free;