From: Ackerley Tng <[email protected]>

Currently, vm_mem_add derives the backing source page size, alignment
padding, and mmap size from the backing source type upfront before checking
if guest_memfd is being mmapped.

With shared memory also mmap()-ed from guest_memfd, the alignment of the
mmap-ed address needs to respect guest_memfd's backing page size.

Refactor the backing store setup to configure the backing source page
size, alignment, mmap flags, and mmap offset directly for guest_memfd
when it is mmapped, ignoring the backing source type.

Skip hugepage validation and anonymous memory madvise calls when mmapping
from guest_memfd, since those are not applicable when mmapping guest_memfd.

Signed-off-by: Ackerley Tng <[email protected]>
---
 tools/testing/selftests/kvm/lib/kvm_util.c | 74 ++++++++++++++++++------------
 1 file changed, 45 insertions(+), 29 deletions(-)

diff --git a/tools/testing/selftests/kvm/lib/kvm_util.c 
b/tools/testing/selftests/kvm/lib/kvm_util.c
index cac5624e99774..3f559f207408f 100644
--- a/tools/testing/selftests/kvm/lib/kvm_util.c
+++ b/tools/testing/selftests/kvm/lib/kvm_util.c
@@ -1034,11 +1034,12 @@ void vm_mem_add(struct kvm_vm *vm, enum 
vm_mem_backing_src_type src_type,
 {
        int ret;
        struct userspace_mem_region *region;
-       size_t backing_src_pagesz = get_backing_src_pagesz(src_type);
-       int mmap_flags = vm_mem_backing_src_alias(src_type)->flag;
        size_t mem_size = npages * vm->page_size;
-       off_t mmap_offset = 0;
-       size_t alignment = 1;
+       size_t backing_src_pagesz;
+       off_t mmap_offset;
+       bool is_gmem_mmap;
+       size_t alignment;
+       int mmap_flags;
 
        TEST_REQUIRE_SET_USER_MEMORY_REGION2();
 
@@ -1090,19 +1091,31 @@ void vm_mem_add(struct kvm_vm *vm, enum 
vm_mem_backing_src_type src_type,
        /* Allocate and initialize new mem region structure. */
        region = calloc(1, sizeof(*region));
        TEST_ASSERT(region != NULL, "Insufficient Memory");
-       region->mmap_size = mem_size;
 
-       /*
-        * When using THP mmap is not guaranteed to returned a hugepage aligned
-        * address so we have to pad the mmap. Padding is not needed for HugeTLB
-        * because mmap will always return an address aligned to the HugeTLB
-        * page size.
-        */
-       if (src_type == VM_MEM_SRC_ANONYMOUS_THP)
-               alignment = max(backing_src_pagesz, alignment);
+       is_gmem_mmap = (flags & KVM_MEM_GUEST_MEMFD) &&
+                      (gmem_flags & GUEST_MEMFD_FLAG_MMAP);
+
+       if (is_gmem_mmap) {
+               backing_src_pagesz = getpagesize();
+               alignment = 1;
+               mmap_flags = MAP_SHARED;
+               mmap_offset = gmem_offset;
+       } else {
+               backing_src_pagesz = get_backing_src_pagesz(src_type);
+               /*
+                * When using THP mmap is not guaranteed to returned a hugepage 
aligned
+                * address so we have to pad the mmap. Padding is not needed 
for HugeTLB
+                * because mmap will always return an address aligned to the 
HugeTLB
+                * page size.
+                */
+               alignment = src_type == VM_MEM_SRC_ANONYMOUS_THP ? 
backing_src_pagesz : 1;
+               mmap_flags = vm_mem_backing_src_alias(src_type)->flag;
+               mmap_offset = 0;
+       }
 
        TEST_ASSERT_EQ(gpa, align_up(gpa, backing_src_pagesz));
 
+       region->mmap_size = mem_size;
        /* Add enough memory to align up if necessary */
        if (alignment > 1)
                region->mmap_size += alignment;
@@ -1129,10 +1142,8 @@ void vm_mem_add(struct kvm_vm *vm, enum 
vm_mem_backing_src_type src_type,
        }
 
        region->fd = -1;
-       if (flags & KVM_MEM_GUEST_MEMFD && gmem_flags & GUEST_MEMFD_FLAG_MMAP) {
+       if (is_gmem_mmap) {
                region->fd = kvm_dup(gmem_fd);
-               mmap_flags = MAP_SHARED;
-               mmap_offset = gmem_offset;
        } else if (backing_src_is_shared(src_type)) {
                region->fd = kvm_memfd_alloc(region->mmap_size,
                                             src_type == 
VM_MEM_SRC_SHARED_HUGETLB);
@@ -1141,22 +1152,27 @@ void vm_mem_add(struct kvm_vm *vm, enum 
vm_mem_backing_src_type src_type,
        region->mmap_start = __kvm_mmap(region->mmap_size, PROT_READ | 
PROT_WRITE,
                                        mmap_flags, region->fd, mmap_offset);
 
-       TEST_ASSERT(!is_backing_src_hugetlb(src_type) ||
-                   region->mmap_start == align_ptr_up(region->mmap_start, 
backing_src_pagesz),
-                   "mmap_start %p is not aligned to HugeTLB page size 0x%lx",
-                   region->mmap_start, backing_src_pagesz);
-
        /* Align host address */
        region->host_mem = align_ptr_up(region->mmap_start, alignment);
 
-       /* As needed perform madvise */
-       if ((src_type == VM_MEM_SRC_ANONYMOUS ||
-            src_type == VM_MEM_SRC_ANONYMOUS_THP) && thp_configured()) {
-               ret = madvise(region->host_mem, mem_size,
-                             src_type == VM_MEM_SRC_ANONYMOUS ? 
MADV_NOHUGEPAGE : MADV_HUGEPAGE);
-               TEST_ASSERT(ret == 0, "madvise failed, addr: %p length: 0x%lx 
src_type: %s",
-                           region->host_mem, mem_size,
-                           vm_mem_backing_src_alias(src_type)->name);
+       if (!is_gmem_mmap) {
+               TEST_ASSERT(!is_backing_src_hugetlb(src_type) ||
+                           region->mmap_start ==
+                           align_ptr_up(region->mmap_start, 
backing_src_pagesz),
+                           "mmap_start %p is not aligned to HugeTLB page size 
0x%lx",
+                           region->mmap_start, backing_src_pagesz);
+
+               /* As needed perform madvise */
+               if ((src_type == VM_MEM_SRC_ANONYMOUS ||
+                    src_type == VM_MEM_SRC_ANONYMOUS_THP) && thp_configured()) 
{
+                       int advice = src_type == VM_MEM_SRC_ANONYMOUS ?
+                                    MADV_NOHUGEPAGE : MADV_HUGEPAGE;
+
+                       ret = madvise(region->host_mem, mem_size, advice);
+                       TEST_ASSERT(ret == 0, "madvise failed, addr: %p length: 
0x%lx src_type: %s",
+                                   region->host_mem, mem_size,
+                                   vm_mem_backing_src_alias(src_type)->name);
+               }
        }
 
        region->backing_src_type = src_type;

-- 
2.55.0.897.gb25b4bd76c-goog



Reply via email to