[PATCH v11 44/46] KVM: selftests: Set up page size and alignment independently for guest_memfd
From: Ackerley Tng
Date: Wed Aug 26 2026 - 05:39:41 EST
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 <ackerleytng@xxxxxxxxxx>
---
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.887.g758fc8c411-goog