[PATCH v5 4/4] selftests: cgroup: handle vmtest-dmem -b to test locally built kernel

From: Albert Esteve

Date: Mon Jul 06 2026 - 08:17:24 EST


Currently vmtest-dmem.sh relies on the host's running kernel or a
pre-built one when booting the virtme-ng VM, with no option to
configure and build a local kernel tree directly.

This adds friction to the development cycle: the user must manually
run vng --kconfig with the correct config fragment, build the kernel,
and pass the result to the script.

Add a -b flag that automates this workflow. When set, handle_build()
configures the kernel using vng --kconfig with the selftest config
fragment, builds it with make -j$(nproc), and run_vm() passes the
local tree to vng --run so the VM boots the freshly built kernel.

Signed-off-by: Eric Chanudet <echanude@xxxxxxxxxx>
Signed-off-by: Albert Esteve <aesteve@xxxxxxxxxx>
---
tools/testing/selftests/cgroup/vmtest-dmem.sh | 47 ++++++++++++++++++++++++---
1 file changed, 43 insertions(+), 4 deletions(-)

diff --git a/tools/testing/selftests/cgroup/vmtest-dmem.sh b/tools/testing/selftests/cgroup/vmtest-dmem.sh
index 0bb6529112b54..4d0e2c0511e5b 100755
--- a/tools/testing/selftests/cgroup/vmtest-dmem.sh
+++ b/tools/testing/selftests/cgroup/vmtest-dmem.sh
@@ -15,6 +15,7 @@ readonly KERNEL_CHECKOUT="$(realpath "${SCRIPT_DIR}"/../../../../)"

source "${SCRIPT_DIR}"/../kselftest/ktap_helpers.sh

+BUILD=0
QEMU="qemu-system-$(uname -m)"
VERBOSE=0
SHELL_MODE=0
@@ -26,10 +27,22 @@ function usage() {
cat <<EOF
$0 [OPTIONS]
Options:
+ -b Build kernel from source tree before booting
-q QEMU binary/path (default: ${QEMU})
-s Start interactive shell in VM instead of running tests
-v Verbose output (vng boot logs on stdout)
-h Display this help
+
+If you build your kernel using KBUILD_OUTPUT= or O= options, these
+can be passed as environment variables to the script:
+
+ O=<build_path> $0 -b
+
+or
+
+ KBUILD_OUTPUT=<build_path> $0 -b
+
+O= takes precedence over KBUILD_OUTPUT= if both are set.
EOF
}

@@ -60,17 +73,41 @@ function check_deps() {
done
}

+function handle_build() {
+ [[ "${BUILD}" -eq 1 ]] || return 0
+
+ [[ -f "${KERNEL_CHECKOUT}/kernel/cgroup/dmem_selftest.c" ]] || \
+ fail "-b requires vmtest-dmem.sh called from the kernel source tree"
+
+ # Figure out where the kernel is being built.
+ # O takes precedence over KBUILD_OUTPUT.
+ local out_args=()
+ if [[ -n "${O:-}" ]]; then
+ out_args=(O="${O}")
+ elif [[ -n "${KBUILD_OUTPUT:-}" ]]; then
+ out_args=(KBUILD_OUTPUT="${KBUILD_OUTPUT}")
+ fi
+
+ pushd "${KERNEL_CHECKOUT}" &>/dev/null
+ vng --kconfig --config "${SCRIPT_DIR}"/config "${out_args[@]}" || \
+ fail "failed to generate .config for kernel source tree (${KERNEL_CHECKOUT})"
+ make "${out_args[@]}" -j"$(nproc 2>/dev/null || echo 1)" || \
+ fail "failed to build kernel from source tree (${KERNEL_CHECKOUT})"
+ popd &>/dev/null
+}
+
# Run vng with common flags. Extra arguments are appended by the caller:
# --exec <script> for automated test runs
# (nothing) for interactive shell mode
function run_vm() {
- local verbose_opt=""
+ local vng_args=()

- [[ "${VERBOSE}" -eq 1 ]] && verbose_opt="--verbose"
+ [[ "${BUILD}" -eq 1 ]] && vng_args+=("${KERNEL_CHECKOUT}")
+ [[ "${VERBOSE}" -eq 1 ]] && vng_args+=("--verbose")

vng \
--run \
- ${verbose_opt:+"${verbose_opt}"} \
+ "${vng_args[@]}" \
--qemu="$(command -v "${QEMU}")" \
--user root \
--rw \
@@ -78,10 +115,11 @@ function run_vm() {
}

function main() {
- while getopts ':hvq:s' opt; do
+ while getopts ':hvq:sb' opt; do
case "${opt}" in
v) VERBOSE=1 ;;
q) QEMU="${OPTARG}" ;;
+ b) BUILD=1 ;;
s) SHELL_MODE=1 ;;
h) usage; exit 0 ;;
*) usage; exit 1 ;;
@@ -89,6 +127,7 @@ function main() {
done

check_deps
+ handle_build

if [[ "${SHELL_MODE}" -eq 1 ]]; then
echo "Starting interactive shell in VM. Exit to stop VM."

--
2.54.0