[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <e51298f79233cc44a14ff2d3659b20cc3767e6bb.1760731772.git.ackerleytng@google.com>
Date: Fri, 17 Oct 2025 13:12:16 -0700
From: Ackerley Tng <ackerleytng@...gle.com>
To: cgroups@...r.kernel.org, kvm@...r.kernel.org, linux-doc@...r.kernel.org,
linux-fsdevel@...r.kernel.org, linux-kernel@...r.kernel.org,
linux-kselftest@...r.kernel.org, linux-mm@...ck.org,
linux-trace-kernel@...r.kernel.org, x86@...nel.org
Cc: ackerleytng@...gle.com, akpm@...ux-foundation.org,
binbin.wu@...ux.intel.com, bp@...en8.de, brauner@...nel.org,
chao.p.peng@...el.com, chenhuacai@...nel.org, corbet@....net,
dave.hansen@...el.com, dave.hansen@...ux.intel.com, david@...hat.com,
dmatlack@...gle.com, erdemaktas@...gle.com, fan.du@...el.com, fvdl@...gle.com,
haibo1.xu@...el.com, hannes@...xchg.org, hch@...radead.org, hpa@...or.com,
hughd@...gle.com, ira.weiny@...el.com, isaku.yamahata@...el.com, jack@...e.cz,
james.morse@....com, jarkko@...nel.org, jgg@...pe.ca, jgowans@...zon.com,
jhubbard@...dia.com, jroedel@...e.de, jthoughton@...gle.com,
jun.miao@...el.com, kai.huang@...el.com, keirf@...gle.com,
kent.overstreet@...ux.dev, liam.merwick@...cle.com,
maciej.wieczor-retman@...el.com, mail@...iej.szmigiero.name,
maobibo@...ngson.cn, mathieu.desnoyers@...icios.com, maz@...nel.org,
mhiramat@...nel.org, mhocko@...nel.org, mic@...ikod.net, michael.roth@....com,
mingo@...hat.com, mlevitsk@...hat.com, mpe@...erman.id.au,
muchun.song@...ux.dev, nikunj@....com, nsaenz@...zon.es,
oliver.upton@...ux.dev, palmer@...belt.com, pankaj.gupta@....com,
paul.walmsley@...ive.com, pbonzini@...hat.com, peterx@...hat.com,
pgonda@...gle.com, prsampat@....com, pvorel@...e.cz, qperret@...gle.com,
richard.weiyang@...il.com, rick.p.edgecombe@...el.com, rientjes@...gle.com,
rostedt@...dmis.org, roypat@...zon.co.uk, rppt@...nel.org, seanjc@...gle.com,
shakeel.butt@...ux.dev, shuah@...nel.org, steven.price@....com,
steven.sistare@...cle.com, suzuki.poulose@....com, tabba@...gle.com,
tglx@...utronix.de, thomas.lendacky@....com, vannapurve@...gle.com,
vbabka@...e.cz, viro@...iv.linux.org.uk, vkuznets@...hat.com,
wei.w.wang@...el.com, will@...nel.org, willy@...radead.org, wyihan@...gle.com,
xiaoyao.li@...el.com, yan.y.zhao@...el.com, yilun.xu@...el.com,
yuzenghui@...wei.com, zhiquan1.li@...el.com
Subject: [RFC PATCH v1 35/37] KVM: selftests: Add script to exercise private_mem_conversions_test
Add a wrapper script to simplify running the private_mem_conversions_test
with a variety of configurations. Manually invoking the test for all
supported memory backing source types is tedious.
The script automatically detects the availability of 2MB and 1GB hugepages
and builds a list of source types to test. It then iterates through the
list, running the test for each type with both a single memslot and
multiple memslots.
This makes it easier to get comprehensive test coverage across different
memory configurations.
Use python to be able to issue an ioctl to /dev/kvm.
Update .gitignore to allowlist python scripts.
Signed-off-by: Ackerley Tng <ackerleytng@...gle.com>
---
tools/testing/selftests/kvm/.gitignore | 1 +
.../kvm/x86/private_mem_conversions_test.py | 159 ++++++++++++++++++
2 files changed, 160 insertions(+)
create mode 100755 tools/testing/selftests/kvm/x86/private_mem_conversions_test.py
diff --git a/tools/testing/selftests/kvm/.gitignore b/tools/testing/selftests/kvm/.gitignore
index 1d41a046a7bfd..d7e9c1d97e376 100644
--- a/tools/testing/selftests/kvm/.gitignore
+++ b/tools/testing/selftests/kvm/.gitignore
@@ -4,6 +4,7 @@
!*.c
!*.h
!*.S
+!*.py
!*.sh
!.gitignore
!config
diff --git a/tools/testing/selftests/kvm/x86/private_mem_conversions_test.py b/tools/testing/selftests/kvm/x86/private_mem_conversions_test.py
new file mode 100755
index 0000000000000..32421ae824d64
--- /dev/null
+++ b/tools/testing/selftests/kvm/x86/private_mem_conversions_test.py
@@ -0,0 +1,159 @@
+#!/usr/bin/env python3
+# SPDX-License-Identifier: GPL-2.0-only
+#
+# Wrapper script which runs different test setups of
+# private_mem_conversions_test.
+#
+# Copyright (C) 2025, Google LLC.
+
+import os
+import fcntl
+import sys
+import subprocess
+
+
+NUM_VCPUS_TO_TEST = 4
+NUM_MEMSLOTS_TO_TEST = NUM_VCPUS_TO_TEST
+
+# Required pages are based on the test setup in the C code.
+# These static requirements are set to the maximum required for
+# NUM_VCPUS_TO_TEST, over all the hugetlb-related tests
+REQUIRED_NUM_2M_HUGEPAGES = 1024 * NUM_VCPUS_TO_TEST
+REQUIRED_NUM_1G_HUGEPAGES = 2 * NUM_VCPUS_TO_TEST
+
+
+def get_hugepage_count(page_size_kb: int) -> int:
+ """Reads the current number of hugepages available for a given size."""
+ try:
+ path = f"/sys/kernel/mm/hugepages/hugepages-{page_size_kb}kB/nr_hugepages"
+ with open(path, 'r') as f:
+ return int(f.read().strip())
+ except (FileNotFoundError, ValueError):
+ return 0
+
+
+def get_default_hugepage_size_in_kb():
+ """Reads the default hugepage size from /proc/meminfo."""
+ try:
+ with open("/proc/meminfo", 'r') as f:
+ for line in f:
+ if line.startswith("Hugepagesize:"):
+ parts = line.split()
+ if len(parts) >= 2 and parts[1].isdigit():
+ return int(parts[1])
+ except FileNotFoundError:
+ return None
+
+
+def run_tests(executable_path: str, src_type: str, num_memslots: int, num_vcpus: int) -> None:
+ """Runs the test executable with different arguments."""
+ print(f"Running tests for backing source type: {src_type}")
+
+ command1 = [executable_path, "-s", src_type, "-m", str(num_memslots)]
+ print(" ".join(command1))
+ _ = subprocess.run(command1, check=True)
+
+ command2 = [executable_path, "-s", src_type, "-m", str(num_memslots), "-n", str(num_vcpus)]
+ print(" ".join(command2))
+ _ = subprocess.run(command2, check=True)
+
+
+def kvm_check_cap(capability: int) -> int:
+ KVM_CHECK_EXTENSION = 0xAE03
+ KVM_DEVICE = '/dev/kvm'
+
+ if not os.path.exists(KVM_DEVICE):
+ print(f"Error: KVM device not found at {KVM_DEVICE}. Is the 'kvm' module loaded?")
+ return -1
+
+ try:
+ fd = os.open(KVM_DEVICE, os.O_RDWR)
+
+ # Issue the ioctl: fcntl.ioctl(fd, request, arg)
+ # request is KVM_CHECK_EXTENSION (0xAE03)
+ # arg is the capability constant (e.g., KVM_CAP_COALESCED_MMIO)
+ result = fcntl.ioctl(fd, KVM_CHECK_EXTENSION, capability)
+
+ os.close(fd)
+ return result
+ except OSError as e:
+ print(f"Error issuing KVM ioctl on {KVM_DEVICE}: {e}", file=sys.stderr)
+ if fd > 0:
+ os.close(fd)
+ return -1
+
+
+def kvm_has_gmem_attributes() -> bool:
+ KVM_CAP_GUEST_MEMFD_MEMORY_ATTRIBUTES = 245
+
+ return kvm_check_cap(KVM_CAP_GUEST_MEMFD_MEMORY_ATTRIBUTES) > 0
+
+
+def get_backing_source_types() -> list[str]:
+ hugepage_2mb_count = get_hugepage_count(2048)
+ hugepage_2mb_enabled = hugepage_2mb_count >= REQUIRED_NUM_2M_HUGEPAGES
+ hugepage_1gb_count = get_hugepage_count(1048576)
+ hugepage_1gb_enabled = hugepage_1gb_count >= REQUIRED_NUM_1G_HUGEPAGES
+
+ default_hugepage_size_kb = get_default_hugepage_size_in_kb()
+ hugepage_default_enabled = False
+ if default_hugepage_size_kb == 2048:
+ hugepage_default_enabled = hugepage_2mb_enabled
+ elif default_hugepage_size_kb == 1048576:
+ hugepage_default_enabled = hugepage_1gb_enabled
+
+ backing_src_types: list[str] = ["anonymous", "anonymous_thp"]
+
+ if hugepage_default_enabled:
+ backing_src_types.append("anonymous_hugetlb")
+ else:
+ print("skipping anonymous_hugetlb backing source type")
+
+ if hugepage_2mb_enabled:
+ backing_src_types.append("anonymous_hugetlb_2mb")
+ else:
+ print("skipping anonymous_hugetlb_2mb backing source type")
+
+ if hugepage_1gb_enabled:
+ backing_src_types.append("anonymous_hugetlb_1gb")
+ else:
+ print("skipping anonymous_hugetlb_1gb backing source type")
+
+ backing_src_types.append("shmem")
+
+ if hugepage_default_enabled:
+ backing_src_types.append("shared_hugetlb")
+ else:
+ print("skipping shared_hugetlb backing source type")
+
+ return backing_src_types
+
+
+def main():
+ script_dir = os.path.dirname(os.path.abspath(__file__))
+ test_executable = os.path.join(script_dir, "private_mem_conversions_test")
+
+ if not os.path.exists(test_executable):
+ print(f"Error: Test executable not found at '{test_executable}'", file=sys.stderr)
+ sys.exit(1)
+
+ return_code = 0
+
+ backing_src_types = ["shmem"] if kvm_has_gmem_attributes() else get_backing_source_types()
+ try:
+ for i, src_type in enumerate(backing_src_types):
+ if i > 0:
+ print()
+ run_tests(test_executable, src_type, NUM_MEMSLOTS_TO_TEST, NUM_VCPUS_TO_TEST)
+ except subprocess.CalledProcessError as e:
+ print(f"Test failed for source type '{src_type}'. Command: {' '.join(e.cmd)}", file=sys.stderr)
+ return_code = e.returncode
+ except Exception as e:
+ print(f"An unexpected error occurred: {e}", file=sys.stderr)
+ return_code = 1
+
+ sys.exit(return_code)
+
+
+if __name__ == "__main__":
+ main()
--
2.51.0.858.gf9c4a03a3a-goog
Powered by blists - more mailing lists