[PATCH] KVM: selftests: Set MPOL_LOCAL explicitly for mmu_stress_test

From: Yan Zhao

Date: Fri Jul 17 2026 - 03:55:53 EST


Set mempolicy MPOL_LOCAL explicitly for mmu_stress_test to avoid its
performance regression (around 30x slowdown) after commit 212d76bef49d
("mm: mempolicy: fix automatic numa balancing for shmem").

mmu_stress_test allocates a large amount of guest memory (128G by default).
The backend of the guest memory is memfd (2G in size by default). To reduce
host memory consumption, all memslots share the same backend, which makes
mmu_stress_test vulnerable to zaps due to MMU notifier invalidation, since
any .invalidate_range_start() notifiction on the HVA of the memfd backend
invalidates all GFNs.

When auto NUMA balancing is enabled, if the VMA for the memfd backend is
not skipped by task_numa_work(), mmu_stress_test suffers severe performance
degradation since any mapping creation would need to wait for mmu_lock or
retry until the invalidation completes. Moreover, there is one
task_numa_work() running on each vCPU thread, each of which triggers KVM to
unmap all memslots, contending KVM's mmu_lock. In a kernel with PREEMPT
configured, the contention could cause KVM's unmapping to proceed very
slowly due to frequent releasing and reacquiring of the mmu_lock. In
testing, this could result in around a 30x+ slowdown, e.g., from
"run1 = 16.297574092s" to "run1 = 482.587258504s".

Previously, the mempolicy of mmu_stress_test defaulted to memfd's policy
when there's no user explicit policy. Since memfd's policy is NULL,
vma_policy_mof() returned 0, causing task_numa_work() to skip the VMA for
the memfd backend. However, after commit 212d76bef49d ("mm: mempolicy: fix
automatic numa balancing for shmem"), vma_policy_mof() now uses the
preferred node policy (MPOL_F_MOF | MPOL_F_MORON) when both user explicit
policy and memfd's policy are NULL, causing auto NUMA balancing to
constantly zap the VMA for the memfd, overwhelming the test with
unnecessary zaps on all guest memory.

Therefore, explicitly set the mempolicy to MPOL_LOCAL to avoid unnecessary
zaps caused by auto NUMA balancing.

Reported-by: Vishal Verma <vishal.l.verma@xxxxxxxxx>
Signed-off-by: Yan Zhao <yan.y.zhao@xxxxxxxxx>
---
tools/testing/selftests/kvm/mmu_stress_test.c | 7 +++++++
1 file changed, 7 insertions(+)

diff --git a/tools/testing/selftests/kvm/mmu_stress_test.c b/tools/testing/selftests/kvm/mmu_stress_test.c
index c799e0d0694f..0c8b12e28602 100644
--- a/tools/testing/selftests/kvm/mmu_stress_test.c
+++ b/tools/testing/selftests/kvm/mmu_stress_test.c
@@ -16,6 +16,7 @@
#include "guest_modes.h"
#include "processor.h"
#include "ucall_common.h"
+#include "numaif.h"

static bool mprotect_ro_done;
static bool all_vcpus_hit_ro_fault;
@@ -269,6 +270,11 @@ static void calc_default_nr_vcpus(void)
nr_vcpus = nr_vcpus * 3/4;
}

+static void set_memory_policy(void)
+{
+ kvm_set_mempolicy(MPOL_LOCAL, NULL, 0);
+}
+
int main(int argc, char *argv[])
{
/*
@@ -304,6 +310,7 @@ int main(int argc, char *argv[])
max_mem = 128ull * SZ_1G;

calc_default_nr_vcpus();
+ set_memory_policy();

while ((opt = getopt(argc, argv, "c:h:m:s:H")) != -1) {
switch (opt) {
--
2.43.2