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 <[email protected]>
> ---
>  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);
> 


Reply via email to