On 6/19/2026 6:01 AM, Ackerley Tng via B4 Relay wrote:
> This is v8 of guest_memfd in-place conversion support.
>
> Up till now, guest_memfd supports the entire inode worth of memory being
> used as all-shared, or all-private. CoCo VMs may request guest memory to be
> converted between private and shared states, and the only way to support
> that currently would be to have the userspace VMM provide two sources of
> backing memory from completely different areas of physical memory.
>
> pKVM has a use case for in-place sharing: the guest and host may be
> cooperating on given data, and pKVM doesn't protect data through
> encryption, so copying that given data between different areas of physical
> memory as part of conversions would be unnecessary work.
>
> This series also serves as a foundation for guest_memfd huge page
> support. Now, guest_memfd only supports PAGE_SIZE pages, so if two sources
> of backing memory are used, the userspace VMM could maintain a steady total
> memory utilized by punching out the pages that are not used. When huge
> pages are available in guest_memfd, even if the backing memory source
> supports hole punching within a huge page, punching out pages to maintain
> the total memory utilized by a VM would be introducing lots of
> fragmentation.
>
> In-place conversion avoids fragmentation by allowing the same physical
> memory to be used for both shared and private memory, with guest_memfd
> tracks the shared/private status of all the pages at a per-page
> granularity.
>
> The central principle, which guest_memfd continues to uphold, is that any
> guest-private page will not be mappable to host userspace. All pages will
> be mmap()-able in host userspace, but accesses to guest-private pages (as
> tracked by guest_memfd) will result in a SIGBUS.
>
> This series introduces a guest_memfd ioctl (not kvm, vm or vcpu, but
> guest_memfd ioctl) that allows userspace to set memory
> attributes (shared/private) directly through the guest_memfd. This is the
> appropriate interface because shared/private-ness is a property of memory
> and hence the request should be sent directly to the memory provider -
> guest_memfd.
>
> Tested with both CONFIG_KVM_VM_MEMORY_ATTRIBUTES enabled and disabled:
>
> + tools/testing/selftests/kvm/guest_memfd_test.c
> + tools/testing/selftests/kvm/pre_fault_memory_test.c
> + tools/testing/selftests/kvm/x86/guest_memfd_conversions_test.c
> + tools/testing/selftests/kvm/x86/private_mem_conversions_test.c
> + tools/testing/selftests/kvm/x86/private_mem_kvm_exits_test.c
>
> Updates for this revision:
>
> + Updated the series to _not_ deprecate all of VM memory attributes, but
> only deprecate tracking of the PRIVATE attributes in VM memory
> attributes. This takes into account upcoming RWX attributes support,
> which will be tracked at the VM level.
> + Reshuffled the earlier commits that deal with preparing KVM to stop
> seeing VM memory attributes as the only source of attributes.
> + Addressed comments from v7
>
> TODOs
>
> + Retest with TDX selftests. v7 was tested with TDX [12], but the setup there was
> wrong. Conversions were successful (no errors), but the shared memory being
> tested is actually in a completely different host physical page.
> + Retest with SNP selftests. v6 was tested with SNP, I ported that to v7
> and those ran fine too. Just need to double-check for v8.
>
> This series is based on kvm-x86/next, and here's the tree for your convenience:
>
> https://github.com/googleprodkernel/linux-cc/commits/guest_memfd-inplace-conversion-v8
>
> Older series:
>
> + RFCv7 is at [11]
> + RFCv6 is at [10]
> + RFCv5 is at [8]
> + RFCv4 is at [7]
> + RFCv3 is at [6]
> + RFCv2 is at [5]
> + RFCv1 is at [4]
> + Previous versions of this feature, part of other series, are available at
> [1][2][3].
>
> [1] https://lore.kernel.org/all/bd163de3118b626d1005aa88e71ef2fb72f0be0f.1726009989.git.ackerleytng@google.com/
> [2] https://lore.kernel.org/all/20250117163001.2326672-6-tabba@google.com/
> [3] https://lore.kernel.org/all/b784326e9ccae6a08388f1bf39db70a2204bdc51.1747264138.git.ackerleytng@google.com/
> [4] https://lore.kernel.org/all/cover.1760731772.git.ackerleytng@google.com/T/
> [5] https://lore.kernel.org/all/cover.1770071243.git.ackerleytng@google.com/T/
> [6] https://lore.kernel.org/r/20260313-gmem-inplace-conversion-v3-0-5fc12a70ec89@google.com/T/
> [7] https://lore.kernel.org/all/20260326-gmem-inplace-conversion-v4-0-e202fe950ffd@google.com/T/
> [8] https://lore.kernel.org/r/20260428-gmem-inplace-conversion-v5-0-d8608ccfca22@google.com
> [9] https://lore.kernel.org/all/20260414-selftest-global-metadata-v1-0-fd223922bc57@google.com/T/
> [10] https://lore.kernel.org/r/20260507-gmem-inplace-conversion-v6-0-91ab5a8b19a4@google.com
> [11] https://lore.kernel.org/r/20260522-gmem-inplace-conversion-v7-0-2f0fae496530@google.com
> [12] https://lore.kernel.org/all/20260605134153.204152-1-ackerleytng@google.com/
>
> Signed-off-by: Ackerley Tng <ackerleytng@google.com>
> ---
> Ackerley Tng (27):
> KVM: Make CONFIG_KVM_VM_MEMORY_ATTRIBUTES selectable
> KVM: Enumerate support for PRIVATE memory iff kvm_arch_has_private_mem is defined
> KVM: guest_memfd: Introduce function to check GFN private/shared status
> KVM: guest_memfd: Only prepare folios for private pages
> KVM: guest_memfd: Add base support for KVM_SET_MEMORY_ATTRIBUTES2
> KVM: guest_memfd: Ensure pages are not in use before conversion
> KVM: guest_memfd: Call arch invalidate hooks on conversion
> KVM: guest_memfd: Return early if range already has requested attributes
> KVM: guest_memfd: Advertise KVM_SET_MEMORY_ATTRIBUTES2 ioctl
> KVM: guest_memfd: Handle lru_add fbatch refcounts during conversion safety check
> KVM: guest_memfd: Use actual size for invalidation in kvm_gmem_release()
> KVM: guest_memfd: Determine invalidation filter from memory attributes
> KVM: guest_memfd: Zero page while getting pfn
> KVM: TDX: Make source page optional for KVM_TDX_INIT_MEM_REGION
> KVM: guest_memfd: Make in-place conversion the default
> KVM: selftests: Test basic single-page conversion flow
> KVM: selftests: Test conversion flow when INIT_SHARED
> KVM: selftests: Test conversion precision in guest_memfd
> KVM: selftests: Test conversion before allocation
> KVM: selftests: Convert with allocated folios in different layouts
> KVM: selftests: Test that truncation does not change shared/private status
> KVM: selftests: Add helpers to pin pages with CONFIG_GUP_TEST
> KVM: selftests: Test conversion with elevated page refcount
> KVM: selftests: Reset shared memory after hole-punching
> KVM: selftests: Provide function to look up guest_memfd details from gpa
> KVM: selftests: Make TEST_EXPECT_SIGBUS thread-safe
> KVM: selftests: Update private_mem_conversions_test to mmap() guest_memfd
>
> Michael Roth (1):
> KVM: SEV: Make 'uaddr' parameter optional for KVM_SEV_SNP_LAUNCH_UPDATE
>
> Sean Christopherson (18):
> KVM: guest_memfd: Introduce per-gmem attributes, use to guard user mappings
> KVM: Rename KVM_GENERIC_MEMORY_ATTRIBUTES to KVM_VM_MEMORY_ATTRIBUTES
> KVM: Move KVM_VM_MEMORY_ATTRIBUTES config definition to x86
> KVM: Decouple kvm_has_arch_private_mem from CONFIG_KVM_VM_MEMORY_ATTRIBUTES
> KVM: Rename memory attribute APIs to prepare for in-place gmem conversion
> KVM: Provide generic interface for checking memory private/shared status
> KVM: guest_memfd: Wire up core private/shared attribute interfaces
> KVM: Consolidate private memory and guest_memfd ifdeffery in kvm_host.h
> KVM: guest_memfd: Enable INIT_SHARED on guest_memfd for x86 Coco VMs
> KVM: selftests: Create gmem fd before "regular" fd when adding memslot
> KVM: selftests: Rename guest_memfd{,_offset} to gmem_{fd,offset}
> KVM: selftests: Add support for mmap() on guest_memfd in core library
> KVM: selftests: Add selftests global for guest memory attributes capability
> KVM: selftests: Add helpers for calling ioctls on guest_memfd
> KVM: selftests: Test that shared/private status is consistent across processes
> KVM: selftests: Provide common function to set memory attributes
> KVM: selftests: Check fd/flags provided to mmap() when setting up memslot
> KVM: selftests: Update private memory exits test to work with per-gmem attributes
>
Hi,
Thanks for this series.
This works well for me on AMD EPYC 7713 (SEV-SNP enabled). I tested:
1. KVM selftests: all tests pass.
2. Using in-place conversion QEMU branch [1]:
qemu-system-x86_64 \
-machine q35,confidential-guest-support=sev0 \
-enable-kvm -cpu EPYC-v4 -smp 8,maxcpus=8 -m 120G -no-reboot \
-object memory-backend-guest-memfd,id=ram0,size=60G,share=on,host-nodes=0-1,policy=interleave \
-object memory-backend-guest-memfd,id=ram1,size=60G,share=on,host-nodes=0,policy=bind \
-numa node,nodeid=0,memdev=ram0,cpus=0-3 \
-numa node,nodeid=1,memdev=ram1,cpus=4-7 \
-object sev-snp-guest,id=sev0,policy=0x30000,cbitpos=51,reduced-phys-bits=1,convert-in-place=on \
-bios "$OVMF" \
-drive file="$DISK",if=none,id=disk0,format=qcow2 \
-device virtio-scsi-pci,id=scsi0,disable-legacy=on,iommu_platform=true -device scsi-hd,drive=disk0 \
-netdev user,id=net0,hostfwd=tcp::8000-:22 -device virtio-net-pci,netdev=net0 \
-kernel "$KERNEL" -initrd "$INITRD" \
-append "$ROOT ro console=ttyS0,115200" \
-trace enable=kvm_convert_memory,file=/tmp/convert.log \
-nographic -serial mon:stdio
The guest boots successfully and run memory hogger. With this, I verified the
shared <-> private conversion logs (trace_kvm_convert_memory).
3. Additionally, verified the NUMA placement for SEV-SNP. With this series,
NUMA mempolicy support for guest_memfd [2] now works for SEV-SNP as well.
[1] https://github.com/amdese/qemu/commits/snp-inplace-rfc1
[2] https://lore.kernel.org/kvm/20251016172853.52451-1-seanjc@google.com
Tested-by: Shivank Garg <shivankg@amd.com>
Best regards,
Shivank