From: Shivank Garg <shivankg@amd.com>
To: <seanjc@google.com>, <david@redhat.com>, <vbabka@suse.cz>,
<willy@infradead.org>, <akpm@linux-foundation.org>,
<shuah@kernel.org>, <pbonzini@redhat.com>, <brauner@kernel.org>,
<viro@zeniv.linux.org.uk>
Cc: <ackerleytng@google.com>, <paul@paul-moore.com>,
<jmorris@namei.org>, <serge@hallyn.com>, <pvorel@suse.cz>,
<bfoster@redhat.com>, <tabba@google.com>, <vannapurve@google.com>,
<chao.gao@intel.com>, <bharata@amd.com>, <nikunj@amd.com>,
<michael.day@amd.com>, <yan.y.zhao@intel.com>,
<Neeraj.Upadhyay@amd.com>, <thomas.lendacky@amd.com>,
<michael.roth@amd.com>, <aik@amd.com>, <jgg@nvidia.com>,
<kalyazin@amazon.com>, <peterx@redhat.com>, <shivankg@amd.com>,
<jack@suse.cz>, <rppt@kernel.org>, <hch@infradead.org>,
<cgzones@googlemail.com>, <ira.weiny@intel.com>,
<rientjes@google.com>, <roypat@amazon.co.uk>, <ziy@nvidia.com>,
<matthew.brost@intel.com>, <joshua.hahnjy@gmail.com>,
<rakie.kim@sk.com>, <byungchul@sk.com>, <gourry@gourry.net>,
<kent.overstreet@linux.dev>, <ying.huang@linux.alibaba.com>,
<apopple@nvidia.com>, <chao.p.peng@intel.com>,
<amit@infradead.org>, <ddutile@redhat.com>,
<dan.j.williams@intel.com>, <ashish.kalra@amd.com>,
<gshan@redhat.com>, <jgowans@amazon.com>, <pankaj.gupta@amd.com>,
<papaluri@amd.com>, <yuzhao@google.com>, <suzuki.poulose@arm.com>,
<quic_eberman@quicinc.com>, <aneeshkumar.kizhakeveetil@arm.com>,
<linux-fsdevel@vger.kernel.org>, <linux-mm@kvack.org>,
<linux-kernel@vger.kernel.org>,
<linux-security-module@vger.kernel.org>, <kvm@vger.kernel.org>,
<linux-kselftest@vger.kernel.org>, <linux-coco@lists.linux.dev>
Subject: [RFC PATCH v8 7/7] KVM: guest_memfd: selftests: Add tests for mmap and NUMA policy support
Date: Wed, 18 Jun 2025 11:29:35 +0000 [thread overview]
Message-ID: <20250618112935.7629-8-shivankg@amd.com> (raw)
In-Reply-To: <20250618112935.7629-1-shivankg@amd.com>
Add tests for NUMA memory policy binding and NUMA aware allocation in
guest_memfd. This extends the existing selftests by adding proper
validation for:
- KVM GMEM set_policy and get_policy() vm_ops functionality using
mbind() and get_mempolicy()
- NUMA policy application before and after memory allocation
These tests help ensure NUMA support for guest_memfd works correctly.
Signed-off-by: Shivank Garg <shivankg@amd.com>
---
tools/testing/selftests/kvm/Makefile.kvm | 1 +
.../testing/selftests/kvm/guest_memfd_test.c | 123 +++++++++++++++++-
2 files changed, 122 insertions(+), 2 deletions(-)
diff --git a/tools/testing/selftests/kvm/Makefile.kvm b/tools/testing/selftests/kvm/Makefile.kvm
index e11ed9e59ab5..f4bb02231d6a 100644
--- a/tools/testing/selftests/kvm/Makefile.kvm
+++ b/tools/testing/selftests/kvm/Makefile.kvm
@@ -273,6 +273,7 @@ pgste-option = $(call try-run, echo 'int main(void) { return 0; }' | \
$(CC) -Werror -Wl$(comma)--s390-pgste -x c - -o "$$TMP",-Wl$(comma)--s390-pgste)
LDLIBS += -ldl
+LDLIBS += -lnuma
LDFLAGS += -pthread $(no-pie-option) $(pgste-option)
LIBKVM_C := $(filter %.c,$(LIBKVM))
diff --git a/tools/testing/selftests/kvm/guest_memfd_test.c b/tools/testing/selftests/kvm/guest_memfd_test.c
index 5da2ed6277ac..a5d261dcfdf5 100644
--- a/tools/testing/selftests/kvm/guest_memfd_test.c
+++ b/tools/testing/selftests/kvm/guest_memfd_test.c
@@ -7,6 +7,8 @@
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
+#include <numa.h>
+#include <numaif.h>
#include <errno.h>
#include <stdio.h>
#include <fcntl.h>
@@ -18,6 +20,7 @@
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
+#include <sys/syscall.h>
#include "kvm_util.h"
#include "test_util.h"
@@ -115,6 +118,122 @@ static void test_mmap_not_supported(int fd, size_t page_size, size_t total_size)
TEST_ASSERT_EQ(mem, MAP_FAILED);
}
+#define TEST_REQUIRE_NUMA_MULTIPLE_NODES() \
+ TEST_REQUIRE(numa_available() != -1 && numa_max_node() >= 1)
+
+static void test_mbind(int fd, size_t page_size, size_t total_size)
+{
+ unsigned long nodemask = 1; /* nid: 0 */
+ unsigned long maxnode = 8;
+ unsigned long get_nodemask;
+ int get_policy;
+ char *mem;
+ int ret;
+
+ TEST_REQUIRE_NUMA_MULTIPLE_NODES();
+
+ mem = mmap(NULL, total_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+ TEST_ASSERT(mem != MAP_FAILED, "mmap for mbind test should succeed");
+
+ /* Test MPOL_INTERLEAVE policy */
+ ret = syscall(__NR_mbind, mem, page_size * 2, MPOL_INTERLEAVE,
+ &nodemask, maxnode, 0);
+ TEST_ASSERT(!ret, "mbind with INTERLEAVE to node 0 should succeed");
+ ret = syscall(__NR_get_mempolicy, &get_policy, &get_nodemask,
+ maxnode, mem, MPOL_F_ADDR);
+ TEST_ASSERT(!ret && get_policy == MPOL_INTERLEAVE && get_nodemask == nodemask,
+ "Policy should be MPOL_INTERLEAVE and nodes match");
+
+ /* Test basic MPOL_BIND policy */
+ ret = syscall(__NR_mbind, mem + page_size * 2, page_size * 2, MPOL_BIND,
+ &nodemask, maxnode, 0);
+ TEST_ASSERT(!ret, "mbind with MPOL_BIND to node 0 should succeed");
+ ret = syscall(__NR_get_mempolicy, &get_policy, &get_nodemask,
+ maxnode, mem + page_size * 2, MPOL_F_ADDR);
+ TEST_ASSERT(!ret && get_policy == MPOL_BIND && get_nodemask == nodemask,
+ "Policy should be MPOL_BIND and nodes match");
+
+ /* Test MPOL_DEFAULT policy */
+ ret = syscall(__NR_mbind, mem, total_size, MPOL_DEFAULT, NULL, 0, 0);
+ TEST_ASSERT(!ret, "mbind with MPOL_DEFAULT should succeed");
+ ret = syscall(__NR_get_mempolicy, &get_policy, &get_nodemask,
+ maxnode, mem, MPOL_F_ADDR);
+ TEST_ASSERT(!ret && get_policy == MPOL_DEFAULT && get_nodemask == 0,
+ "Policy should be MPOL_DEFAULT and nodes zero");
+
+ /* Test with invalid policy */
+ ret = syscall(__NR_mbind, mem, page_size, 999, &nodemask, maxnode, 0);
+ TEST_ASSERT(ret == -1 && errno == EINVAL,
+ "mbind with invalid policy should fail with EINVAL");
+
+ TEST_ASSERT(munmap(mem, total_size) == 0, "munmap should succeed");
+}
+
+static void test_numa_allocation(int fd, size_t page_size, size_t total_size)
+{
+ unsigned long node0_mask = 1; /* Node 0 */
+ unsigned long node1_mask = 2; /* Node 1 */
+ unsigned long maxnode = 8;
+ void *pages[4];
+ int status[4];
+ char *mem;
+ int ret, i;
+
+ TEST_REQUIRE_NUMA_MULTIPLE_NODES();
+
+ /* Clean slate: deallocate all file space, if any */
+ ret = fallocate(fd, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE, 0, total_size);
+ TEST_ASSERT(!ret, "fallocate(PUNCH_HOLE) should succeed");
+
+ mem = mmap(NULL, total_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+ TEST_ASSERT(mem != MAP_FAILED, "mmap should succeed");
+
+ for (i = 0; i < 4; i++)
+ pages[i] = (char *)mem + page_size * i;
+
+ /* Set NUMA policy after allocation */
+ memset(mem, 0xaa, page_size);
+ ret = syscall(__NR_mbind, pages[0], page_size, MPOL_BIND, &node0_mask, maxnode, 0);
+ TEST_ASSERT(!ret, "mbind after allocation page 0 to node 0 should succeed");
+ ret = fallocate(fd, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE, 0, page_size);
+ TEST_ASSERT(!ret, "fallocate(PUNCH_HOLE) should succeed");
+
+ /* Set NUMA policy before allocation */
+ ret = syscall(__NR_mbind, pages[0], page_size * 2, MPOL_BIND, &node1_mask, maxnode, 0);
+ TEST_ASSERT(!ret, "mbind page 0, 1 to node 1 should succeed");
+ ret = syscall(__NR_mbind, pages[2], page_size * 2, MPOL_BIND, &node0_mask, maxnode, 0);
+ TEST_ASSERT(!ret, "mbind page 2, 3 to node 0 should succeed");
+ memset(mem, 0xaa, total_size);
+
+ /* Validate if pages are allocated on specified NUMA nodes */
+ ret = syscall(__NR_move_pages, 0, 4, pages, NULL, status, 0);
+ TEST_ASSERT(ret >= 0, "move_pages should succeed for status check");
+ TEST_ASSERT(status[0] == 1, "Page 0 should be allocated on node 1");
+ TEST_ASSERT(status[1] == 1, "Page 1 should be allocated on node 1");
+ TEST_ASSERT(status[2] == 0, "Page 2 should be allocated on node 0");
+ TEST_ASSERT(status[3] == 0, "Page 3 should be allocated on node 0");
+
+ /* Punch hole for all pages */
+ ret = fallocate(fd, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE, 0, total_size);
+ TEST_ASSERT(!ret, "fallocate(PUNCH_HOLE) should succeed");
+
+ /* Change NUMA policy nodes and reallocate */
+ ret = syscall(__NR_mbind, pages[0], page_size * 2, MPOL_BIND, &node0_mask, maxnode, 0);
+ TEST_ASSERT(!ret, "mbind page 0, 1 to node 0 should succeed");
+ ret = syscall(__NR_mbind, pages[2], page_size * 2, MPOL_BIND, &node1_mask, maxnode, 0);
+ TEST_ASSERT(!ret, "mbind page 2, 3 to node 1 should succeed");
+ memset(mem, 0xaa, total_size);
+
+ ret = syscall(__NR_move_pages, 0, 4, pages, NULL, status, 0);
+ TEST_ASSERT(ret >= 0, "move_pages should succeed after reallocation");
+ TEST_ASSERT(status[0] == 0, "Page 0 should be allocated on node 0");
+ TEST_ASSERT(status[1] == 0, "Page 1 should be allocated on node 0");
+ TEST_ASSERT(status[2] == 1, "Page 2 should be allocated on node 1");
+ TEST_ASSERT(status[3] == 1, "Page 3 should be allocated on node 1");
+
+ TEST_ASSERT(munmap(mem, total_size) == 0, "munmap should succeed");
+}
+
static void test_file_size(int fd, size_t page_size, size_t total_size)
{
struct stat sb;
@@ -275,7 +394,8 @@ static void test_with_type(unsigned long vm_type, uint64_t guest_memfd_flags,
if (expect_mmap_allowed) {
test_mmap_supported(fd, page_size, total_size);
test_fault_overflow(fd, page_size, total_size);
-
+ test_mbind(fd, page_size, total_size);
+ test_numa_allocation(fd, page_size, total_size);
} else {
test_mmap_not_supported(fd, page_size, total_size);
}
--
2.43.0
prev parent reply other threads:[~2025-06-18 11:32 UTC|newest]
Thread overview: 35+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-06-18 11:29 [RFC PATCH v8 0/7] Add NUMA mempolicy support for KVM guest-memfd Shivank Garg
2025-06-18 11:29 ` [RFC PATCH v8 1/7] security: Export anon_inode_make_secure_inode for KVM guest_memfd Shivank Garg
2025-06-18 11:29 ` [RFC PATCH v8 2/7] KVM: guest_memfd: Use guest mem inodes instead of anonymous inodes Shivank Garg
2025-06-18 11:29 ` [RFC PATCH v8 3/7] mm/filemap: Add mempolicy support to the filemap layer Shivank Garg
2025-06-19 15:08 ` Vlastimil Babka
2025-06-19 16:03 ` Matthew Wilcox
2025-06-20 5:59 ` Shivank Garg
2025-06-20 9:37 ` Vlastimil Babka
2025-06-20 14:34 ` Matthew Wilcox
2025-06-20 14:52 ` Shivank Garg
2025-06-20 14:58 ` Matthew Wilcox
2025-06-20 14:34 ` [PATCH 1/2] filemap: Add a mempolicy argument to filemap_alloc_folio() Matthew Wilcox (Oracle)
2025-06-23 6:13 ` Gupta, Pankaj
2025-06-23 7:19 ` Vlastimil Babka
2025-06-20 14:34 ` [PATCH 2/2] filemap: Add __filemap_get_folio_mpol() Matthew Wilcox (Oracle)
2025-06-20 16:53 ` Matthew Wilcox
2025-06-22 18:43 ` Andrew Morton
2025-06-22 19:02 ` Shivank Garg
2025-06-22 22:16 ` Andrew Morton
2025-06-23 4:18 ` Shivank Garg
2025-06-23 10:01 ` Shivank Garg
2025-06-23 7:16 ` Vlastimil Babka
2025-06-23 9:56 ` Shivank Garg
2025-06-21 18:42 ` kernel test robot
2025-06-23 6:15 ` Gupta, Pankaj
2025-06-23 7:20 ` Vlastimil Babka
2025-06-18 11:29 ` [RFC PATCH v8 4/7] mm/mempolicy: Export memory policy symbols Shivank Garg
2025-06-18 15:12 ` Gregory Price
2025-06-19 11:13 ` Shivank Garg
2025-06-19 16:28 ` Vlastimil Babka
2025-06-18 11:29 ` [RFC PATCH v8 5/7] KVM: guest_memfd: Add slab-allocated inode cache Shivank Garg
2025-06-24 4:16 ` Huang, Ying
2025-06-29 18:25 ` Shivank Garg
2025-06-18 11:29 ` [RFC PATCH v8 6/7] KVM: guest_memfd: Enforce NUMA mempolicy using shared policy Shivank Garg
2025-06-18 11:29 ` Shivank Garg [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20250618112935.7629-8-shivankg@amd.com \
--to=shivankg@amd.com \
--cc=Neeraj.Upadhyay@amd.com \
--cc=ackerleytng@google.com \
--cc=aik@amd.com \
--cc=akpm@linux-foundation.org \
--cc=amit@infradead.org \
--cc=aneeshkumar.kizhakeveetil@arm.com \
--cc=apopple@nvidia.com \
--cc=ashish.kalra@amd.com \
--cc=bfoster@redhat.com \
--cc=bharata@amd.com \
--cc=brauner@kernel.org \
--cc=byungchul@sk.com \
--cc=cgzones@googlemail.com \
--cc=chao.gao@intel.com \
--cc=chao.p.peng@intel.com \
--cc=dan.j.williams@intel.com \
--cc=david@redhat.com \
--cc=ddutile@redhat.com \
--cc=gourry@gourry.net \
--cc=gshan@redhat.com \
--cc=hch@infradead.org \
--cc=ira.weiny@intel.com \
--cc=jack@suse.cz \
--cc=jgg@nvidia.com \
--cc=jgowans@amazon.com \
--cc=jmorris@namei.org \
--cc=joshua.hahnjy@gmail.com \
--cc=kalyazin@amazon.com \
--cc=kent.overstreet@linux.dev \
--cc=kvm@vger.kernel.org \
--cc=linux-coco@lists.linux.dev \
--cc=linux-fsdevel@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-kselftest@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=linux-security-module@vger.kernel.org \
--cc=matthew.brost@intel.com \
--cc=michael.day@amd.com \
--cc=michael.roth@amd.com \
--cc=nikunj@amd.com \
--cc=pankaj.gupta@amd.com \
--cc=papaluri@amd.com \
--cc=paul@paul-moore.com \
--cc=pbonzini@redhat.com \
--cc=peterx@redhat.com \
--cc=pvorel@suse.cz \
--cc=quic_eberman@quicinc.com \
--cc=rakie.kim@sk.com \
--cc=rientjes@google.com \
--cc=roypat@amazon.co.uk \
--cc=rppt@kernel.org \
--cc=seanjc@google.com \
--cc=serge@hallyn.com \
--cc=shuah@kernel.org \
--cc=suzuki.poulose@arm.com \
--cc=tabba@google.com \
--cc=thomas.lendacky@amd.com \
--cc=vannapurve@google.com \
--cc=vbabka@suse.cz \
--cc=viro@zeniv.linux.org.uk \
--cc=willy@infradead.org \
--cc=yan.y.zhao@intel.com \
--cc=ying.huang@linux.alibaba.com \
--cc=yuzhao@google.com \
--cc=ziy@nvidia.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.