Re: [PATCH v15 13/23] KVM: selftests: Support guest_memfd in-place conversion

From: Binbin Wu

Date: Fri Oct 09 2026 - 23:33:00 EST


On 10/2/2026 3:37 AM, Lisa Wang wrote:
> With guest_memfd in-place conversion, the memory region can be set as
> shared, eliminating the need for dual-backed memory.
>
> By setting the region to shared initially, the KVM selftest framework
> can populate the mmap()-ed guest_memfd memory just like any standard
> memory provider.
>
> For CoCo VMs, pages that need to be private are explicitly set to
> private before executing the VM.
>
> Signed-off-by: Lisa Wang <wyihan@xxxxxxxxxx>
> ---
> tools/testing/selftests/kvm/lib/kvm_util.c | 20 ++++++++++++++------
> tools/testing/selftests/kvm/lib/x86/tdx/tdx_util.c | 6 +++++-
> 2 files changed, 19 insertions(+), 7 deletions(-)
>
> diff --git a/tools/testing/selftests/kvm/lib/kvm_util.c b/tools/testing/selftests/kvm/lib/kvm_util.c
> index 7625908caf21..f474664b5d92 100644
> --- a/tools/testing/selftests/kvm/lib/kvm_util.c
> +++ b/tools/testing/selftests/kvm/lib/kvm_util.c
> @@ -494,8 +494,10 @@ struct kvm_vm *__vm_create(struct vm_shape shape, u32 nr_runnable_vcpus,
> u64 nr_pages = vm_nr_pages_required(shape.mode, nr_runnable_vcpus,
> nr_extra_pages);
> struct userspace_mem_region *slot0;
> + u64 gmem_flags = 0;
> struct kvm_vm *vm;
> - int i, flags;
> + int flags = 0;
> + int i;
>
> kvm_set_files_rlimit(nr_runnable_vcpus);
>
> @@ -505,14 +507,20 @@ struct kvm_vm *__vm_create(struct vm_shape shape, u32 nr_runnable_vcpus,
> vm = ____vm_create(shape);
>
> /*
> - * Force GUEST_MEMFD for the primary memory region if necessary, e.g.
> - * for CoCo VMs that require GUEST_MEMFD backed private memory.
> + * Force GUEST_MEMFD for the primary memory region if necessary, and
> + * initialize it as shared if in-place conversion is supported, so the
> + * selftest framework can populate it exactly like other memory
> + * providers.
> */
> - flags = 0;
> - if (is_guest_memfd_required(shape))
> + if (is_guest_memfd_required(shape)) {
> flags |= KVM_MEM_GUEST_MEMFD;
> + if (kvm_has_gmem_attributes)
> + gmem_flags |= GUEST_MEMFD_FLAG_INIT_SHARED |
> + GUEST_MEMFD_FLAG_MMAP;
> + }
>
> - vm_userspace_mem_region_add(vm, VM_MEM_SRC_ANONYMOUS, 0, 0, nr_pages, flags);
> + vm_mem_add(vm, VM_MEM_SRC_ANONYMOUS, 0, 0, nr_pages, flags,
> + -1, 0, gmem_flags);

This is common for both TDX and SNP, does it break SNP?


> for (i = 0; i < NR_MEM_REGIONS; i++)
> vm->memslots[i] = 0;
>
> diff --git a/tools/testing/selftests/kvm/lib/x86/tdx/tdx_util.c b/tools/testing/selftests/kvm/lib/x86/tdx/tdx_util.c
> index e348507a6be8..40ee9b1951c2 100644
> --- a/tools/testing/selftests/kvm/lib/x86/tdx/tdx_util.c
> +++ b/tools/testing/selftests/kvm/lib/x86/tdx/tdx_util.c
> @@ -23,6 +23,8 @@ void tdx_vm_setup_boot_code_region(struct kvm_vm *vm)
> gpa_t gpa;
> u8 *hva;
>
> + if (kvm_has_gmem_attributes)
> + gmem_flags |= GUEST_MEMFD_FLAG_INIT_SHARED | GUEST_MEMFD_FLAG_MMAP;
> vm_mem_add(vm, VM_MEM_SRC_SHMEM, alloc_gpa, TD_BOOT_CODE_SLOT,
> nr_pages, KVM_MEM_GUEST_MEMFD, -1, 0, gmem_flags);
>
> @@ -44,9 +46,11 @@ void tdx_vm_setup_boot_parameters_region(struct kvm_vm *vm, u32 nr_runnable_vcpu
> size_t boot_params_size = sizeof(struct td_boot_parameters) +
> nr_runnable_vcpus * sizeof(struct td_per_vcpu_parameters);
> int npages = DIV_ROUND_UP(boot_params_size, PAGE_SIZE);
> - const u64 gmem_flags = 0;
> + u64 gmem_flags = 0;
> gpa_t gpa;
>
> + if (kvm_has_gmem_attributes)
> + gmem_flags |= GUEST_MEMFD_FLAG_INIT_SHARED | GUEST_MEMFD_FLAG_MMAP;
> vm_mem_add(vm, VM_MEM_SRC_SHMEM, TD_BOOT_PARAMETERS_GPA,
> TD_BOOT_PARAMETERS_SLOT, npages,
> KVM_MEM_GUEST_MEMFD, -1, 0, gmem_flags);
>