[PATCH v15 13/23] KVM: selftests: Support guest_memfd in-place conversion
From: Lisa Wang
Date: Thu Oct 01 2026 - 15:41:28 EST
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);
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);
--
2.56.0.rc1.315.gc6ed9934b7-goog