[Devel] [PATCH vz10 v2] selftests: build test modules against the kernel tree
Eva Kurchatova
eva.kurchatova at virtuozzo.com
Wed Aug 12 12:49:17 MSK 2026
Selftests livepatch, cgroup and mm/page_frag build out-of-tree kernel
modules and default KDIR to /lib/modules/$(uname -r)/build, which is
the running kernel build tree on the currently building host.
That is wrong whenever the selftests are built as part of a kernel
package: `uname -r` is not the kernel being packaged, so the modules
either are not built at all (no source tree for the builders kernel)
or come out with the wrong vermagic and symbol layout.
Either way no usable test modules end up in the packaged test suite,
and a testing host may not have the kernel build tree to compile them
either, so the tests will fail.
Default KDIR to the kernel tree the tests are built from, or to its O=
build directory, whenever that tree is configured and built.
This is exactly what bpf/test_kmods has been already doing all along,
and its modules are built and packaged that way today. Pick the build
directory up from O= or KBUILD_OUTPUT, and resolve a relative one
against the source tree, the way kbuild resolves it as well.
Testing for include/config/auto.conf and Module.symvers keeps the previous
behaviour for a bare source checkout, and for a source tree that was
mrpropered after the kernel had been built (packaging copies
Module.symvers back into such a tree), so nothing that builds today
starts failing.
Also test for $(KDIR)/Makefile rather than for $(KDIR) itself before
descending into the kernel tree: /lib/modules/$(uname -r)/build is
commonly a dangling symlink, which the previous test accepted before
failing in make -C. The same protection is applied to bpf/test_kmods
and mm/page_frag, which had no such check at all.
Give bpf/test_kmods the same treatment while at it, so that every
in-tree test module picks KDIR the same way: it hardcoded the source
tree with no regard for O=, and failed outright instead of falling
back when that tree was not configured.
In an O= build KDIR is the build directory, which carries the generated
configuration but not the source headers. mm/Makefile decides whether
to build page_frag_test.ko by looking for include/linux/page_frag_cache.h
below KDIR, so look for that header through the "source" symlink that
outputmakefile leaves in the build directory as well, otherwise an O=
build skips the module and blames a too old kernel for it. Split
kernel-devel packages that keep sources and build artifacts apart carry
the same symlink.
With this, `make kselftest TARGETS=livepatch` in a built kernel tree
builds the modules for that kernel and `make install` ships them, so an
installed testsuite runs against pre-built modules and needs no kernel
build tree at all.
Signed-off-by: Eva Kurchatova <eva.kurchatova at virtuozzo.com>
https://virtuozzo.atlassian.net/browse/VSTOR-139647
Feature: fix selftests
---
Changes since v1:
- Look for page_frag_cache.h through the "source" symlink as well.
v1 tested $(KDIR)/include/linux/page_frag_cache.h only, but in an O=
build KDIR is the build directory, which carries the generated
configuration and no source headers at all.
mm/Makefile therefore left TEST_GEN_MODS_DIR unset, lib.mk never
descended into page_frag/, page_frag_test.ko was neither built nor
installed, and the build blamed a too old kernel for it.
Before v1 that case built the module against
/lib/modules/$(uname -r)/build, where the header is present, so v1
did regress it.
- Resolve a relative O= against the source tree.
v1 fed O= to $(abspath ...), which resolves against the directory of
the Makefile being read, so make -C <suite> O=../../../../out placed
the build directory several levels off and silently fell back to
/lib/modules/$(uname -r)/build. Going through the top level
selftests Makefile was unaffected, it hands an absolute path down.
- Honour KBUILD_OUTPUT, not only O=, since kbuild treats the two the
same and a suite Makefile invoked directly never sees the O= that
the top level selftests Makefile derives from it.
- Apply the same KDIR selection and the $(KDIR)/Makefile test to
bpf/test_kmods, so that all in-tree test modules pick their kernel
build tree the same way. It hardcoded the source tree, ignoring O=,
and failed the build instead of falling back when that tree was not
configured.
- Derive the source tree in mm/Makefile from MAKEFILE_LIST rather than
from $(CURDIR), to match the other four Makefiles and to not depend
on make having been entered with -C.
.../testing/selftests/bpf/test_kmods/Makefile | 30 ++++++++++++++++-
.../selftests/cgroup/test_modules/Makefile | 33 ++++++++++++++++---
.../selftests/livepatch/test_modules/Makefile | 33 ++++++++++++++++---
tools/testing/selftests/mm/Makefile | 33 ++++++++++++++++++-
tools/testing/selftests/mm/page_frag/Makefile | 30 +++++++++++++++++
5 files changed, 149 insertions(+), 10 deletions(-)
diff --git a/tools/testing/selftests/bpf/test_kmods/Makefile b/tools/testing/selftests/bpf/test_kmods/Makefile
index d4e50c4509c9..2353140505d6 100644
--- a/tools/testing/selftests/bpf/test_kmods/Makefile
+++ b/tools/testing/selftests/bpf/test_kmods/Makefile
@@ -1,5 +1,25 @@
TEST_KMOD_DIR := $(realpath $(dir $(abspath $(lastword $(MAKEFILE_LIST)))))
-KDIR ?= $(abspath $(TEST_KMOD_DIR)/../../../../..)
+
+# Kernel build tree to compile the test modules against. This already
+# defaulted to the kernel tree these tests are part of; also honour its
+# O= or KBUILD_OUTPUT build directory, and fall back to the running
+# kernel's build tree when the tree is not configured and built, so that
+# all in-tree test modules pick KDIR the same way.
+KSRC_TREE := $(abspath $(TEST_KMOD_DIR)/../../../../..)
+KOUT := $(or $(O),$(KBUILD_OUTPUT))
+ifeq ($(KOUT),)
+KDIR_TREE := $(KSRC_TREE)
+else ifneq (,$(filter /%,$(KOUT)))
+KDIR_TREE := $(abspath $(KOUT))
+else
+KDIR_TREE := $(abspath $(KSRC_TREE)/$(KOUT))
+endif
+ifneq (,$(wildcard $(KDIR_TREE)/include/config/auto.conf))
+ifneq (,$(wildcard $(KDIR_TREE)/Module.symvers))
+KDIR ?= $(KDIR_TREE)
+endif
+endif
+KDIR ?= /lib/modules/$(shell uname -r)/build
ifeq ($(V),1)
Q =
@@ -14,8 +34,16 @@ $(foreach m,$(MODULES),$(eval obj-m += $(m:.ko=.o)))
CFLAGS_bpf_testmod.o = -I$(src)
+# Ensure that KDIR is a kernel build tree, otherwise skip the compilation.
+# Testing for the Makefile rather than for the directory itself also covers
+# a dangling /lib/modules/$(uname -r)/build symlink.
all:
+ifneq ("$(wildcard $(KDIR)/Makefile)", "")
$(Q)$(MAKE) -C $(KDIR) M=$(TEST_KMOD_DIR) modules
+endif
+# Ensure that KDIR is a kernel build tree, otherwise skip the clean target
clean:
+ifneq ("$(wildcard $(KDIR)/Makefile)", "")
$(Q)$(MAKE) -C $(KDIR) M=$(TEST_KMOD_DIR) clean
+endif
diff --git a/tools/testing/selftests/cgroup/test_modules/Makefile b/tools/testing/selftests/cgroup/test_modules/Makefile
index 3f39eeda3a92..1dc531589b15 100644
--- a/tools/testing/selftests/cgroup/test_modules/Makefile
+++ b/tools/testing/selftests/cgroup/test_modules/Makefile
@@ -1,17 +1,42 @@
TESTMODS_DIR := $(realpath $(dir $(abspath $(lastword $(MAKEFILE_LIST)))))
+
+# Kernel build tree to compile the test modules against. Prefer the
+# kernel tree these tests are part of (or its O= build directory) when it
+# is configured and built, like bpf/test_kmods already does: When the
+# selftests are built as part of a kernel package, uname -r is the build
+# host's kernel and not the kernel being packaged, so the resulting
+# modules would carry the wrong vermagic and symbol layout. Fall back to
+# the running kernel's build tree for standalone builds.
+KSRC_TREE := $(abspath $(TESTMODS_DIR)/../../../../..)
+KOUT := $(or $(O),$(KBUILD_OUTPUT))
+ifeq ($(KOUT),)
+KDIR_TREE := $(KSRC_TREE)
+else ifneq (,$(filter /%,$(KOUT)))
+KDIR_TREE := $(abspath $(KOUT))
+else
+KDIR_TREE := $(abspath $(KSRC_TREE)/$(KOUT))
+endif
+ifneq (,$(wildcard $(KDIR_TREE)/include/config/auto.conf))
+ifneq (,$(wildcard $(KDIR_TREE)/Module.symvers))
+KDIR ?= $(KDIR_TREE)
+endif
+endif
KDIR ?= /lib/modules/$(shell uname -r)/build
obj-m += cg_freezer_hang.o \
cg_freezer_kthread.o
-# Ensure that KDIR exists, otherwise skip the compilation
+# Ensure that KDIR is a kernel build tree, otherwise skip the compilation.
+# Testing for the Makefile rather than for the directory itself also covers
+# a dangling /lib/modules/$(uname -r)/build symlink, and an installed
+# testsuite, which ships pre-built modules and has no kernel tree above it.
modules:
-ifneq ("$(wildcard $(KDIR))", "")
+ifneq ("$(wildcard $(KDIR)/Makefile)", "")
$(Q)$(MAKE) -C $(KDIR) modules KBUILD_EXTMOD=$(TESTMODS_DIR)
endif
-# Ensure that KDIR exists, otherwise skip the clean target
+# Ensure that KDIR is a kernel build tree, otherwise skip the clean target
clean:
-ifneq ("$(wildcard $(KDIR))", "")
+ifneq ("$(wildcard $(KDIR)/Makefile)", "")
$(Q)$(MAKE) -C $(KDIR) clean KBUILD_EXTMOD=$(TESTMODS_DIR)
endif
diff --git a/tools/testing/selftests/livepatch/test_modules/Makefile b/tools/testing/selftests/livepatch/test_modules/Makefile
index 939230e571f5..66dcbd842f71 100644
--- a/tools/testing/selftests/livepatch/test_modules/Makefile
+++ b/tools/testing/selftests/livepatch/test_modules/Makefile
@@ -1,4 +1,26 @@
TESTMODS_DIR := $(realpath $(dir $(abspath $(lastword $(MAKEFILE_LIST)))))
+
+# Kernel build tree to compile the test modules against. Prefer the
+# kernel tree these tests are part of (or its O= build directory) when it
+# is configured and built, like bpf/test_kmods already does: when the
+# selftests are built as part of a kernel package, uname -r is the build
+# host's kernel and not the kernel being packaged, so the resulting
+# modules would carry the wrong vermagic and symbol CRCs. Fall back to
+# the running kernel's build tree for standalone builds.
+KSRC_TREE := $(abspath $(TESTMODS_DIR)/../../../../..)
+KOUT := $(or $(O),$(KBUILD_OUTPUT))
+ifeq ($(KOUT),)
+KDIR_TREE := $(KSRC_TREE)
+else ifneq (,$(filter /%,$(KOUT)))
+KDIR_TREE := $(abspath $(KOUT))
+else
+KDIR_TREE := $(abspath $(KSRC_TREE)/$(KOUT))
+endif
+ifneq (,$(wildcard $(KDIR_TREE)/include/config/auto.conf))
+ifneq (,$(wildcard $(KDIR_TREE)/Module.symvers))
+KDIR ?= $(KDIR_TREE)
+endif
+endif
KDIR ?= /lib/modules/$(shell uname -r)/build
obj-m += test_klp_atomic_replace.o \
@@ -14,14 +36,17 @@ obj-m += test_klp_atomic_replace.o \
test_klp_state3.o \
test_klp_syscall.o
-# Ensure that KDIR exists, otherwise skip the compilation
+# Ensure that KDIR is a kernel build tree, otherwise skip the compilation.
+# Testing for the Makefile rather than for the directory itself also covers
+# a dangling /lib/modules/$(uname -r)/build symlink, and an installed
+# testsuite, which ships pre-built modules and has no kernel tree above it.
modules:
-ifneq ("$(wildcard $(KDIR))", "")
+ifneq ("$(wildcard $(KDIR)/Makefile)", "")
$(Q)$(MAKE) -C $(KDIR) modules KBUILD_EXTMOD=$(TESTMODS_DIR)
endif
-# Ensure that KDIR exists, otherwise skip the clean target
+# Ensure that KDIR is a kernel build tree, otherwise skip the clean target
clean:
-ifneq ("$(wildcard $(KDIR))", "")
+ifneq ("$(wildcard $(KDIR)/Makefile)", "")
$(Q)$(MAKE) -C $(KDIR) clean KBUILD_EXTMOD=$(TESTMODS_DIR)
endif
diff --git a/tools/testing/selftests/mm/Makefile b/tools/testing/selftests/mm/Makefile
index 3de23ea4663f..1d6bb5cf9e08 100644
--- a/tools/testing/selftests/mm/Makefile
+++ b/tools/testing/selftests/mm/Makefile
@@ -36,9 +36,40 @@ MAKEFLAGS += --no-builtin-rules
CFLAGS = -Wall -I $(top_srcdir) $(EXTRA_CFLAGS) $(KHDR_INCLUDES) $(TOOLS_INCLUDES)
LDLIBS = -lrt -lpthread -lm
+# Kernel build tree to compile page_frag_test.ko against. Prefer the
+# kernel tree these tests are part of (or its O= build directory) when it
+# is configured and built, like bpf/test_kmods already does: when the
+# selftests are built as part of a kernel package, uname -r is the build
+# host's kernel and not the kernel being packaged, so the resulting module
+# would carry the wrong vermagic and symbol CRCs. Fall back to the
+# running kernel's build tree for standalone builds. Keep this in sync
+# with page_frag/Makefile, which is invoked separately by lib.mk.
+KSRC_TREE := $(abspath $(dir $(abspath $(lastword $(MAKEFILE_LIST))))/../../../..)
+KOUT := $(or $(O),$(KBUILD_OUTPUT))
+ifeq ($(KOUT),)
+KDIR_TREE := $(KSRC_TREE)
+else ifneq (,$(filter /%,$(KOUT)))
+KDIR_TREE := $(abspath $(KOUT))
+else
+KDIR_TREE := $(abspath $(KSRC_TREE)/$(KOUT))
+endif
+ifneq (,$(wildcard $(KDIR_TREE)/include/config/auto.conf))
+ifneq (,$(wildcard $(KDIR_TREE)/Module.symvers))
+KDIR ?= $(KDIR_TREE)
+endif
+endif
KDIR ?= /lib/modules/$(shell uname -r)/build
+
+# A build directory holds the generated configuration but no source
+# headers, so look for the header through the "source" symlink that
+# outputmakefile leaves in an O= build directory as well. Split
+# kernel-devel packages carry the same symlink.
+PAGE_FRAG_HDR := $(firstword $(wildcard \
+ $(KDIR)/include/linux/page_frag_cache.h \
+ $(KDIR)/source/include/linux/page_frag_cache.h))
+
ifneq (,$(wildcard $(KDIR)/Module.symvers))
-ifneq (,$(wildcard $(KDIR)/include/linux/page_frag_cache.h))
+ifneq (,$(PAGE_FRAG_HDR))
TEST_GEN_MODS_DIR := page_frag
else
PAGE_FRAG_WARNING = "missing page_frag_cache.h, please use a newer kernel"
diff --git a/tools/testing/selftests/mm/page_frag/Makefile b/tools/testing/selftests/mm/page_frag/Makefile
index 8c8bb39ffa28..f7bc03f5d914 100644
--- a/tools/testing/selftests/mm/page_frag/Makefile
+++ b/tools/testing/selftests/mm/page_frag/Makefile
@@ -1,4 +1,26 @@
PAGE_FRAG_TEST_DIR := $(realpath $(dir $(abspath $(lastword $(MAKEFILE_LIST)))))
+
+# Kernel build tree to compile the test module against. Prefer the kernel
+# tree this test is part of (or its O= build directory) when it is
+# configured and built, like bpf/test_kmods already does: when the
+# selftests are built as part of a kernel package, uname -r is the build
+# host's kernel and not the kernel being packaged, so the resulting module
+# would carry the wrong vermagic and symbol CRCs. Fall back to the
+# running kernel's build tree for standalone builds.
+KSRC_TREE := $(abspath $(PAGE_FRAG_TEST_DIR)/../../../../..)
+KOUT := $(or $(O),$(KBUILD_OUTPUT))
+ifeq ($(KOUT),)
+KDIR_TREE := $(KSRC_TREE)
+else ifneq (,$(filter /%,$(KOUT)))
+KDIR_TREE := $(abspath $(KOUT))
+else
+KDIR_TREE := $(abspath $(KSRC_TREE)/$(KOUT))
+endif
+ifneq (,$(wildcard $(KDIR_TREE)/include/config/auto.conf))
+ifneq (,$(wildcard $(KDIR_TREE)/Module.symvers))
+KDIR ?= $(KDIR_TREE)
+endif
+endif
KDIR ?= /lib/modules/$(shell uname -r)/build
ifeq ($(V),1)
@@ -11,8 +33,16 @@ MODULES = page_frag_test.ko
obj-m += page_frag_test.o
+# Ensure that KDIR is a kernel build tree, otherwise skip the compilation.
+# Testing for the Makefile rather than for the directory itself also covers
+# a dangling /lib/modules/$(uname -r)/build symlink, and an installed
+# testsuite, which ships a pre-built module and has no kernel tree above it.
all:
+ifneq ("$(wildcard $(KDIR)/Makefile)", "")
+$(Q)make -C $(KDIR) M=$(PAGE_FRAG_TEST_DIR) modules
+endif
clean:
+ifneq ("$(wildcard $(KDIR)/Makefile)", "")
+$(Q)make -C $(KDIR) M=$(PAGE_FRAG_TEST_DIR) clean
+endif
--
2.55.0
More information about the Devel
mailing list