[PATCH v14 13/22] KVM: selftests: Support guest_memfd in-place conversion

From: Lisa Wang

Date: Wed Jul 22 2026 - 19:23:41 EST


Set the memory region as shared if guest_memfd in-place conversion is
support, so that the KVM selftest framework functions can populate
mmap()-ed guest_memfd memory the same way memory from other memory
providers are populated.

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 | 8 ++++++--
2 files changed, 20 insertions(+), 8 deletions(-)

diff --git a/tools/testing/selftests/kvm/lib/kvm_util.c b/tools/testing/selftests/kvm/lib/kvm_util.c
index 4a48c4b42095..e547ea341ff7 100644
--- a/tools/testing/selftests/kvm/lib/kvm_util.c
+++ b/tools/testing/selftests/kvm/lib/kvm_util.c
@@ -484,8 +484,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);

@@ -495,14 +497,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 support, 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);
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 2ce8c297f7ed..5bbe51ad0f66 100644
--- a/tools/testing/selftests/kvm/lib/x86/tdx/tdx_util.c
+++ b/tools/testing/selftests/kvm/lib/x86/tdx/tdx_util.c
@@ -17,10 +17,12 @@ void tdx_vm_setup_boot_code_region(struct kvm_vm *vm)
gpa_t boot_code_gpa = X86_RESET_VECTOR - TD_BOOT_CODE_SIZE;
gpa_t alloc_gpa = round_down(boot_code_gpa, PAGE_SIZE);
size_t nr_pages = DIV_ROUND_UP(total_code_size, PAGE_SIZE);
- const u64 gmem_flags = 0;
+ u64 gmem_flags = 0;
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);

@@ -56,9 +58,11 @@ void tdx_vm_setup_boot_parameters_region(struct kvm_vm *vm, u32 nr_runnable_vcpu
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);

--
2.55.0.229.g6434b31f56-goog