From: Shuah Khan <skhan@linuxfoundation.org>
To: Linus Torvalds <torvalds@linux-foundation.org>
Cc: shuah <shuah@kernel.org>, Shuah Khan <skhan@linuxfoundation.org>,
linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org
Subject: [GIT PULL] kselftest next update for Linux 7.4-rc1
Date: Wed, 21 Oct 2026 13:34:16 -0600 [thread overview]
Message-ID: <4017e436-9f32-4cdb-a75d-4cbfcddd69f4@linuxfoundation.org> (raw)
[-- Attachment #1: Type: text/plain, Size: 6278 bytes --]
Hi Linus,
Please pull the kselftest next update for Linux 7.4-rc1.
- Improves selftest build, run-time, and install framework
Installs even when some modules fail to build, prints summary of test
results at the end of the default test run, keeps the build status from
wrapping to success so build errors are reported, and optionally records
per-suite build and install results:
selftests: lib.mk: Don't fail install if no modules were built
selftests/lib.mk: run_tests: print summary at the end
selftests: keep the build status from wrapping to success
selftests: optionally record per-suite build and install results
- Adds LLVM support to kselftest_deps.sh
selftests: kselftest_deps.sh: Support LLVM
- Fixes resctrl, breakpoints suspend, ftrace, and tracing tests
selftests/resctrl: Skip L3_CAT when no exclusive cache portion exists
selftests: breakpoints: Skip step_after_suspend_test on systems
without a wakeup capable RTC
selftests/ftrace: skip gcov symbols when picking a function to probe
selftests/ftrace: Avoid unlink error on first run
selftests/ftrace: Add nice dependency
tracing/selftests: Fix incorrect invocation of exit_fail
- Fixes and enhances resctrl test use link lists to manage IMC counters
selftests/resctrl: Introduce linked list management for IMC counters
selftests/resctrl: Replace counter index references with pointers
selftests/resctrl: Enable dynamic management of IMC counters via
linked list
diff is attached.
thanks,
-- Shuah
----------------------------------------------------------------
The following changes since commit cee9395acd8043be0644b25c34bfa86623f2b935:
Linux 7.3-rc1 (2026-08-30 13:34:40 -0700)
are available in the Git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/shuah/linux-kselftest tags/linux_kselftest-next-7.4-rc1
for you to fetch changes up to 368e5d4d12a802ee3708800319cd13904721286f:
selftests: breakpoints: Skip step_after_suspend_test on systems without a wakeup capable RTC (2026-10-19 18:05:00 -0600)
----------------------------------------------------------------
linux_kselftest-next-7.4-rc1
- Improves selftest build, run-time, and install framework
Installs even when some modules fail to build, prints summary of test
results at the end of the default test run, keeps the build status from
wrapping to success so build errors are reported, and optionally records
per-suite build and install results:
selftests: lib.mk: Don't fail install if no modules were built
selftests/lib.mk: run_tests: print summary at the end
selftests: keep the build status from wrapping to success
selftests: optionally record per-suite build and install results
- Adds LLVM support to kselftest_deps.sh
selftests: kselftest_deps.sh: Support LLVM
- Fixes resctrl, breakpoints suspend, ftrace, and tracing tests
selftests/resctrl: Skip L3_CAT when no exclusive cache portion exists
selftests: breakpoints: Skip step_after_suspend_test on systems
without a wakeup capable RTC
selftests/ftrace: skip gcov symbols when picking a function to probe
selftests/ftrace: Avoid unlink error on first run
selftests/ftrace: Add nice dependency
tracing/selftests: Fix incorrect invocation of exit_fail
- Fixes and enhances resctrl test use link lists to manage IMC counters
selftests/resctrl: Introduce linked list management for IMC counters
selftests/resctrl: Replace counter index references with pointers
selftests/resctrl: Enable dynamic management of IMC counters via
linked list
----------------------------------------------------------------
Anirudh Srinivasan (1):
selftests: breakpoints: Skip step_after_suspend_test on systems without a wakeup capable RTC
Eva Kurchatova (1):
selftests/ftrace: skip gcov symbols when picking a function to probe
Jaewon Jung (2):
selftests/ftrace: Avoid unlink error on first run
selftests/ftrace: Add nice dependency
Mark Brown (2):
selftests: lib.mk: Don't fail install if no modules were built
selftests: kselftest_deps.sh: Support LLVM
Matthieu Baerts (NGI0) (1):
selftests/lib.mk: run_tests: print summary at the end
Richard Cheng (1):
selftests/resctrl: Skip L3_CAT when no exclusive cache portion exists
Sasha Levin (2):
selftests: keep the build status from wrapping to success
selftests: optionally record per-suite build and install results
Woradorn Laodhanadhaworn (1):
tracing/selftests: Fix incorrect invocation of exit_fail
Yifan Wu (3):
selftests/resctrl: Introduce linked list management for IMC counters
selftests/resctrl: Replace counter index references with pointers
selftests/resctrl: Enable dynamic management of IMC counters via linked list
Documentation/dev-tools/kselftest.rst | 38 +++++
tools/testing/selftests/Makefile | 31 +++-
.../breakpoints/step_after_suspend_test.c | 11 ++
tools/testing/selftests/build_report.mk | 26 ++++
tools/testing/selftests/ftrace/ftracetest | 2 +-
.../test.d/00basic/ringbuffer_subbuf_size.tc | 6 +-
.../ftrace/test.d/00basic/trace_marker.tc | 4 +-
.../ftrace/test.d/kprobe/kprobe_eventname.tc | 2 +-
.../inter-event/trigger-onchange-action-hist.tc | 2 +-
.../inter-event/trigger-snapshot-action-hist.tc | 2 +-
tools/testing/selftests/kselftest_deps.sh | 83 +++++++++-
tools/testing/selftests/lib.mk | 5 +-
tools/testing/selftests/resctrl/cat_test.c | 23 ++-
tools/testing/selftests/resctrl/mba_test.c | 1 +
tools/testing/selftests/resctrl/mbm_test.c | 1 +
tools/testing/selftests/resctrl/resctrl.h | 2 +
tools/testing/selftests/resctrl/resctrl_val.c | 169 +++++++++++----------
17 files changed, 304 insertions(+), 104 deletions(-)
create mode 100644 tools/testing/selftests/build_report.mk
----------------------------------------------------------------
[-- Attachment #2: linux_kselftest-next-7.4-rc1.diff --]
[-- Type: text/x-patch, Size: 31108 bytes --]
diff --git a/Documentation/dev-tools/kselftest.rst b/Documentation/dev-tools/kselftest.rst
index 64c0ec7428a2..26a536ef4cd6 100644
--- a/Documentation/dev-tools/kselftest.rst
+++ b/Documentation/dev-tools/kselftest.rst
@@ -133,6 +133,44 @@ build successfully; make will abort as soon as any target fails::
This applies to both the ``all`` and ``install`` targets and is useful in
CI environments where a silent partial build would be misleading.
+Recording suite build results
+=============================
+
+Since the build succeeds as long as one target builds, the exit status of
+make does not show which targets failed. Set ``KSFT_BUILD_REPORT`` to the
+absolute path of a file to have the ``all`` and ``install`` targets append
+a tab-separated record for each target they process::
+
+ $ : > /tmp/ksft-build.tsv
+ $ make -C tools/testing/selftests O=/tmp/kernel-build \
+ KSFT_BUILD_REPORT=/tmp/ksft-build.tsv install
+
+Each record holds the phase (``all`` or ``install``), a name and the exit
+status of that step. Recording does not change which targets are built or
+installed, or the exit status of make, also with ``FORCE_TARGETS=1``. The
+caller creates or truncates the report before a build; the rules only
+append to it. Nothing is recorded by ``make -n``, ``-t`` or ``-q``.
+
+The same name can appear several times: ``install`` builds the targets
+again, and generating ``kselftest-list.txt`` is recorded as part of the
+``install`` phase. Targets that are added automatically as installation
+dependencies of other targets, such as ``net/lib``, are recorded too.
+Suites that are built from several subdirectories may also record each
+subdirectory under its path, for example ``arm64/tags``; a failure there
+means that the suite was built or installed only partially. A record
+belongs to the target with the longest name that is equal to the record
+name or followed by ``/`` in it.
+
+A target was built and installed successfully only if all of its records
+have a zero status. Missing records do not show that a target was built.
+A successful target that installs no tests has no entries in
+``kselftest-list.txt``. Install the kernel headers with ``make headers``
+before building: a suite that fails because the headers are missing is
+recorded as failed even if a later step installs them.
+
+``KSFT_BUILD_REPORT_VERSION`` in tools/testing/selftests/Makefile gives the
+version of this format, currently ``1``.
+
Running the full range hotplug selftests
========================================
diff --git a/tools/testing/selftests/Makefile b/tools/testing/selftests/Makefile
index 2d960626750e..d4c71ad20bbb 100644
--- a/tools/testing/selftests/Makefile
+++ b/tools/testing/selftests/Makefile
@@ -171,6 +171,10 @@ endif
# of the targets gets built.
FORCE_TARGETS ?=
+# Remember dry runs for the build report before MAKEFLAGS may be cleared.
+KSFT_BUILD_REPORT_DRY_RUN := $(strip $(foreach f,n t q,$(findstring $(f),$(firstword -$(MAKEFLAGS)))))
+export KSFT_BUILD_REPORT_DRY_RUN
+
# Clear LDFLAGS and MAKEFLAGS when implicit rules are missing. This provides
# implicit rules to sub-test Makefiles which avoids build failures in test
# Makefile that don't have explicit build rules.
@@ -215,6 +219,10 @@ ARCH ?= $(SUBARCH)
export BUILD
export KHDR_INCLUDES
+# Version of the optional KSFT_BUILD_REPORT format written by these rules.
+KSFT_BUILD_REPORT_VERSION := 1
+include $(top_srcdir)/tools/testing/selftests/build_report.mk
+
# set default goal to all, so make without a target runs all, even when
# all isn't the first target in the file.
.DEFAULT_GOAL := all
@@ -223,11 +231,13 @@ all:
@ret=1; \
for TARGET in $(TARGETS) $(INSTALL_DEP_TARGETS); do \
BUILD_TARGET=$$BUILD/$$TARGET; \
- mkdir $$BUILD_TARGET -p; \
+ mkdir -p $$BUILD_TARGET && \
$(MAKE) OUTPUT=$$BUILD_TARGET -C $$TARGET \
- O=$(abs_objtree) \
- $(if $(FORCE_TARGETS),|| exit); \
- ret=$$((ret * $$?)); \
+ O=$(abs_objtree); \
+ status=$$?; \
+ $(call ksft_record_build_status,all,$$TARGET); \
+ $(if $(FORCE_TARGETS),[ $$status -eq 0 ] || exit $$status;) \
+ [ $$status -eq 0 ] && ret=0; \
done; exit $$ret;
run_tests: all
@@ -284,7 +294,7 @@ ifdef INSTALL_PATH
install -m 744 kselftest/ktap_helpers.sh $(INSTALL_PATH)/kselftest/
install -m 744 kselftest/ksft.py $(INSTALL_PATH)/kselftest/
install -m 744 run_kselftest.sh $(INSTALL_PATH)/
- rm -f $(TEST_LIST)
+ : > $(TEST_LIST)
@ret=1; \
for TARGET in $(TARGETS) $(INSTALL_DEP_TARGETS); do \
BUILD_TARGET=$$BUILD/$$TARGET; \
@@ -292,9 +302,11 @@ ifdef INSTALL_PATH
INSTALL_PATH=$(INSTALL_PATH)/$$TARGET \
SRC_PATH=$(shell readlink -e $$(pwd)) \
OBJ_PATH=$(INSTALL_PATH) \
- O=$(abs_objtree) \
- $(if $(FORCE_TARGETS),|| exit); \
- ret=$$((ret * $$?)); \
+ O=$(abs_objtree); \
+ status=$$?; \
+ $(call ksft_record_build_status,install,$$TARGET); \
+ $(if $(FORCE_TARGETS),[ $$status -eq 0 ] || exit $$status;) \
+ [ $$status -eq 0 ] && ret=0; \
done; exit $$ret;
@@ -308,6 +320,9 @@ ifdef INSTALL_PATH
printf "Emit Tests for $$TARGET\n"; \
$(MAKE) -s --no-print-directory OUTPUT=$$BUILD_TARGET COLLECTION=$$TARGET \
-C $$TARGET emit_tests >> $(TEST_LIST); \
+ status=$$?; \
+ $(call ksft_record_build_status,install,$$TARGET); \
+ (exit $$status); \
done;
@VERSION=$$(git describe HEAD 2>/dev/null); \
if [ -n "$$VERSION" ]; then \
diff --git a/tools/testing/selftests/breakpoints/step_after_suspend_test.c b/tools/testing/selftests/breakpoints/step_after_suspend_test.c
index ca2aaab9e4ca..727790259429 100644
--- a/tools/testing/selftests/breakpoints/step_after_suspend_test.c
+++ b/tools/testing/selftests/breakpoints/step_after_suspend_test.c
@@ -18,6 +18,7 @@
#include <sys/timerfd.h>
#include <sys/types.h>
#include <sys/wait.h>
+#include <time.h>
#include "kselftest.h"
@@ -158,11 +159,21 @@ void suspend(void)
int err;
int count_before;
int count_after;
+ struct timespec res;
struct itimerspec spec = {};
if (getuid() != 0)
ksft_exit_skip("Please run the test as root - Exiting.\n");
+ /*
+ * CLOCK_BOOTTIME_ALARM cannot wake up systems that don't have a
+ * wakeup capable RTC from suspend. Check if we have a wakeup-capable
+ * RTC to prevent this test from causing the system to hang after
+ * it suspends.
+ */
+ if (clock_getres(CLOCK_BOOTTIME_ALARM, &res) != 0)
+ ksft_exit_skip("No wakeup-capable RTC for CLOCK_BOOTTIME_ALARM\n");
+
timerfd = timerfd_create(CLOCK_BOOTTIME_ALARM, 0);
if (timerfd < 0)
ksft_exit_fail_msg("timerfd_create() failed\n");
diff --git a/tools/testing/selftests/build_report.mk b/tools/testing/selftests/build_report.mk
new file mode 100644
index 000000000000..047c239925e1
--- /dev/null
+++ b/tools/testing/selftests/build_report.mk
@@ -0,0 +1,26 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# Optional per-suite build report, see "Recording suite build results" in
+# Documentation/dev-tools/kselftest.rst. Callers set KSFT_BUILD_REPORT to an
+# absolute filename and use ksft_record_build_status from a shell loop that
+# has stored the exit status of the recorded step in $status.
+
+ifneq (x$(KSFT_BUILD_REPORT)x,xx)
+ifeq ($(filter x/%,$(firstword x$(KSFT_BUILD_REPORT))),)
+$(error KSFT_BUILD_REPORT must be an absolute path: '$(KSFT_BUILD_REPORT)')
+endif
+endif
+export KSFT_BUILD_REPORT
+
+ksft_build_report_dry_run := $(KSFT_BUILD_REPORT_DRY_RUN) \
+ $(foreach f,n t q,$(findstring $(f),$(firstword -$(MAKEFLAGS))))
+
+ifneq ($(strip $(ksft_build_report_dry_run)),)
+ksft_record_build_status = :
+else
+define ksft_record_build_status
+if [ -n "$$KSFT_BUILD_REPORT" ]; then \
+ printf '%s\t%s\t%d\n' '$(1)' "$(2)" "$$status" >> "$$KSFT_BUILD_REPORT" || exit 1; \
+fi
+endef
+endif
diff --git a/tools/testing/selftests/ftrace/ftracetest b/tools/testing/selftests/ftrace/ftracetest
index 246d7e1d015c..95804610e079 100755
--- a/tools/testing/selftests/ftrace/ftracetest
+++ b/tools/testing/selftests/ftrace/ftracetest
@@ -243,7 +243,7 @@ else
mkdir -p $LOG_DIR || errexit "Failed to make a log directory: $LOG_DIR"
date > $LOG_FILE
if [ "x-$LINK_PTR" != "x-" ]; then
- unlink $LINK_PTR
+ rm -f $LINK_PTR
ln -fs $LOG_DATE $LINK_PTR
fi
fi
diff --git a/tools/testing/selftests/ftrace/test.d/00basic/ringbuffer_subbuf_size.tc b/tools/testing/selftests/ftrace/test.d/00basic/ringbuffer_subbuf_size.tc
index d44d09a33a74..8cfe59d32b1f 100644
--- a/tools/testing/selftests/ftrace/test.d/00basic/ringbuffer_subbuf_size.tc
+++ b/tools/testing/selftests/ftrace/test.d/00basic/ringbuffer_subbuf_size.tc
@@ -60,7 +60,7 @@ test_buffer() {
# the size must be greater than or equal to page_size - data_offset
page_size=$((page_size-data_offset))
if [ $size -lt $page_size ]; then
- exit fail
+ exit_fail
fi
# Now add a little more the meta data overhead will overflow
@@ -71,14 +71,14 @@ test_buffer() {
new_str=`awk ' /tracing_mark_write:/ { sub(/^.*tracing_mark_write: /,"");printf "%s", $0; exit}' trace`
if [ "$new_str" = "$str" ]; then
- exit fail;
+ exit_fail
fi
# Make sure the entire line can be found
new_str=`awk ' /tracing_mark_write:/ { sub(/^.*tracing_mark_write: /,"");printf "%s", $0; }' trace`
if [ "$new_str" != "$str" ]; then
- exit fail;
+ exit_fail
fi
}
diff --git a/tools/testing/selftests/ftrace/test.d/00basic/trace_marker.tc b/tools/testing/selftests/ftrace/test.d/00basic/trace_marker.tc
index 9aa0db2b84fc..1986c1bf1606 100644
--- a/tools/testing/selftests/ftrace/test.d/00basic/trace_marker.tc
+++ b/tools/testing/selftests/ftrace/test.d/00basic/trace_marker.tc
@@ -68,14 +68,14 @@ test_buffer() {
new_str=`awk ' /tracing_mark_write:/ { sub(/^.*tracing_mark_write: /,"");printf "%s", $0; exit}' trace`
if [ "$new_str" = "$str" ]; then
- exit fail;
+ exit_fail
fi
# Make sure the entire line can be found
new_str=`awk ' /tracing_mark_write:/ { sub(/^.*tracing_mark_write: /,"");printf "%s", $0; }' trace`
if [ "$new_str" != "$str" ]; then
- exit fail;
+ exit_fail
fi
}
diff --git a/tools/testing/selftests/ftrace/test.d/kprobe/kprobe_eventname.tc b/tools/testing/selftests/ftrace/test.d/kprobe/kprobe_eventname.tc
index ba19b81cef39..0688a5c47d1e 100644
--- a/tools/testing/selftests/ftrace/test.d/kprobe/kprobe_eventname.tc
+++ b/tools/testing/selftests/ftrace/test.d/kprobe/kprobe_eventname.tc
@@ -5,7 +5,7 @@
:;: "Add an event on function without name" ;:
-FUNC=`grep " [tT] .*vfs_read$" /proc/kallsyms | tail -n 1 | cut -f 3 -d " "`
+FUNC=`grep " [tT] .*vfs_read$" /proc/kallsyms | grep -v __gcov | tail -n 1 | cut -f 3 -d " "`
[ "x" != "x$FUNC" ] || exit_unresolved
echo "p $FUNC" > kprobe_events
PROBE_NAME=`echo $FUNC | tr ".:" "_"`
diff --git a/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-onchange-action-hist.tc b/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-onchange-action-hist.tc
index 55ab0270e5f7..04e6db2a734d 100644
--- a/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-onchange-action-hist.tc
+++ b/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-onchange-action-hist.tc
@@ -1,7 +1,7 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
# description: event trigger - test inter-event histogram trigger onchange action
-# requires: set_event "onchange(var)":README ping:program
+# requires: set_event "onchange(var)":README ping:program nice:program
# flags: instance
fail() { #msg
diff --git a/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-snapshot-action-hist.tc b/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-snapshot-action-hist.tc
index 9eb37c2fa417..64bb0dca7e3b 100644
--- a/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-snapshot-action-hist.tc
+++ b/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-snapshot-action-hist.tc
@@ -1,7 +1,7 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
# description: event trigger - test inter-event histogram trigger snapshot action
-# requires: set_event snapshot events/sched/sched_process_fork/hist "onchange(var)":README "snapshot()":README ping:program
+# requires: set_event snapshot events/sched/sched_process_fork/hist "onchange(var)":README "snapshot()":README ping:program nice:program
# flags: instance
fail() { #msg
diff --git a/tools/testing/selftests/kselftest_deps.sh b/tools/testing/selftests/kselftest_deps.sh
index 487e49fdf2a6..70b834361cb7 100755
--- a/tools/testing/selftests/kselftest_deps.sh
+++ b/tools/testing/selftests/kselftest_deps.sh
@@ -10,13 +10,20 @@
usage()
{
-echo -e "Usage: $0 -[p] <compiler> [test_name]\n"
+echo -e "Usage: $0 -[p] <compiler> [ARCH=<arch>] [test_name]\n"
echo -e "\tkselftest_deps.sh [-p] gcc"
echo -e "\tkselftest_deps.sh [-p] gcc mm"
echo -e "\tkselftest_deps.sh [-p] aarch64-linux-gnu-gcc"
-echo -e "\tkselftest_deps.sh [-p] aarch64-linux-gnu-gcc mm\n"
+echo -e "\tkselftest_deps.sh [-p] aarch64-linux-gnu-gcc mm"
+echo -e "\tkselftest_deps.sh [-p] LLVM"
+echo -e "\tkselftest_deps.sh [-p] LLVM ARCH=arm64 mm\n"
echo "- Should be run in selftests directory in the kernel repo."
echo "- Checks if Kselftests can be built/cross-built on a system."
+echo "- Compiler can be given as LLVM to use clang, as with LLVM=1 in"
+echo " the kselftest build. LLVM=<prefix>/ and LLVM=-<suffix> select"
+echo " the clang binary as in the kselftest build. ARCH=<arch> selects"
+echo " the clang target architecture, defaulting to the host; it is"
+echo " ignored for other compilers."
echo "- Parses all test/sub-test Makefile to find library dependencies."
echo "- Runs compile test on a trivial C file with LDLIBS specified"
echo " in the test Makefiles to identify missing library dependencies."
@@ -53,13 +60,32 @@ while getopts "p" arg; do
esac
done
+# Pull an optional ARCH=<arch> out of the remaining arguments. The
+# environment is used if it is not given on the command line, as with
+# make.
+args=()
+for arg in "$@"; do
+ case "$arg" in
+ ARCH=*)
+ ARCH=${arg#ARCH=};;
+ *)
+ args+=("$arg");;
+ esac
+done
+set -- "${args[@]}"
+
if [ $# -eq 0 ]
then
usage
fi
# Compiler
-CC=$1
+case "$1" in
+ LLVM|LLVM=*)
+ setup_llvm "${1#LLVM}";;
+ *)
+ CC=$1;;
+esac
tmp_file=$(mktemp).c
trap "rm -f $tmp_file.o $tmp_file $tmp_file.bin" EXIT
@@ -178,6 +204,56 @@ exit $?
}
# end main()
+# Mirror the LLVM handling in lib.mk: LLVM=<prefix>/ or LLVM=-<suffix>
+# select the clang binary, and ARCH selects the target triple with the
+# host as the default.
+setup_llvm()
+{
+ local llvm=${1#=}
+ local llvm_prefix=""
+ local llvm_suffix=""
+ local clang
+ local target
+
+ declare -A clang_target
+ clang_target[arm]=arm-linux-gnueabi
+ clang_target[arm64]=aarch64-linux-gnu
+ clang_target[hexagon]=hexagon-linux-musl
+ clang_target[i386]=i386-linux-gnu
+ clang_target[m68k]=m68k-linux-gnu
+ clang_target[mips]=mipsel-linux-gnu
+ clang_target[powerpc]=powerpc64le-linux-gnu
+ clang_target[riscv]=riscv64-linux-gnu
+ clang_target[s390]=s390x-linux-gnu
+ clang_target[x86]=x86_64-linux-gnu
+ clang_target[x86_64]=x86_64-linux-gnu
+
+ case "$llvm" in
+ */)
+ llvm_prefix=$llvm;;
+ -*)
+ llvm_suffix=$llvm;;
+ esac
+ clang=${llvm_prefix}clang${llvm_suffix}
+
+ if [ -z "$ARCH" ]; then
+ target=$($clang -print-target-triple 2>/dev/null)
+ if [ -z "$target" ]; then
+ echo -e "\tUnable to run $clang ..."
+ exit 1
+ fi
+ else
+ target=${clang_target[$ARCH]}
+ if [ -z "$target" ]; then
+ echo -e "\tUnknown ARCH $ARCH for LLVM, supported:"
+ echo -e "\t$(echo "${!clang_target[*]}" | xargs -n1 | sort | xargs)"
+ exit 1
+ fi
+ fi
+
+ CC="$clang --target=$target -fintegrated-as"
+}
+
all_tests()
{
for test in $l1_tests; do
@@ -285,6 +361,7 @@ print_results()
{
echo -e "========================================================";
echo -e "Kselftest Dependency Check for [$0 $1 $2] results..."
+ echo -e "Compiler: $CC"
if [ $print_targets -ne 0 ]
then
diff --git a/tools/testing/selftests/lib.mk b/tools/testing/selftests/lib.mk
index f02cc8a2e4ae..881f13ee2c8a 100644
--- a/tools/testing/selftests/lib.mk
+++ b/tools/testing/selftests/lib.mk
@@ -106,7 +106,8 @@ define RUN_TESTS
if [ "X$(summary)" != "X" ]; then \
per_test_logging=1; \
fi; \
- run_many $(1)
+ run_many $(1); \
+ ktap_print_totals
endef
define INSTALL_INCLUDES
@@ -155,7 +156,7 @@ endef
define INSTALL_MODS_RULE
$(if $(INSTALL_LIST),@mkdir -p $(INSTALL_PATH)/$(INSTALL_LIST))
- $(if $(INSTALL_LIST),rsync -a --copy-unsafe-links $(INSTALL_LIST)/*.ko $(INSTALL_PATH)/$(INSTALL_LIST))
+ $(if $(wildcard $(INSTALL_LIST)/*.ko),rsync -a --copy-unsafe-links $(INSTALL_LIST)/*.ko $(INSTALL_PATH)/$(INSTALL_LIST))
endef
define INSTALL_RULE
diff --git a/tools/testing/selftests/resctrl/cat_test.c b/tools/testing/selftests/resctrl/cat_test.c
index 371a2f26dc47..0a417267dd74 100644
--- a/tools/testing/selftests/resctrl/cat_test.c
+++ b/tools/testing/selftests/resctrl/cat_test.c
@@ -357,11 +357,32 @@ static bool noncont_cat_feature_check(const struct resctrl_test *test)
return resource_info_file_exists(test->resource, "sparse_masks");
}
+static bool cat_feature_check(const struct resctrl_test *test)
+{
+ unsigned long mask;
+
+ if (!test_resource_feature_check(test))
+ return false;
+
+ /*
+ * Test requires an exclusive cache portion. Some platforms may
+ * legitimately report all bits as shareable, skip the test if that
+ * is the case.
+ */
+ if (get_mask_no_shareable(test->resource, &mask)) {
+ ksft_print_msg("All %s bits are shareable, test requires an exclusive cache portion\n",
+ test->resource);
+ return false;
+ }
+
+ return true;
+}
+
struct resctrl_test l3_cat_test = {
.name = "L3_CAT",
.group = "CAT",
.resource = "L3",
- .feature_check = test_resource_feature_check,
+ .feature_check = cat_feature_check,
.run_test = cat_run_test,
.cleanup = cat_test_cleanup,
};
diff --git a/tools/testing/selftests/resctrl/mba_test.c b/tools/testing/selftests/resctrl/mba_test.c
index 39cee9898359..4bb1a82eb195 100644
--- a/tools/testing/selftests/resctrl/mba_test.c
+++ b/tools/testing/selftests/resctrl/mba_test.c
@@ -166,6 +166,7 @@ static int check_results(void)
static void mba_test_cleanup(void)
{
+ cleanup_read_mem_bw_imc();
remove(RESULT_FILE_NAME);
}
diff --git a/tools/testing/selftests/resctrl/mbm_test.c b/tools/testing/selftests/resctrl/mbm_test.c
index 6dbbc3b76003..68c89f50a34a 100644
--- a/tools/testing/selftests/resctrl/mbm_test.c
+++ b/tools/testing/selftests/resctrl/mbm_test.c
@@ -125,6 +125,7 @@ static int mbm_measure(const struct user_params *uparams,
static void mbm_test_cleanup(void)
{
+ cleanup_read_mem_bw_imc();
remove(RESULT_FILE_NAME);
}
diff --git a/tools/testing/selftests/resctrl/resctrl.h b/tools/testing/selftests/resctrl/resctrl.h
index 175101022bf3..a7556cdae0de 100644
--- a/tools/testing/selftests/resctrl/resctrl.h
+++ b/tools/testing/selftests/resctrl/resctrl.h
@@ -24,6 +24,7 @@
#include <linux/perf_event.h>
#include <linux/compiler.h>
#include <linux/bits.h>
+#include <linux/list.h>
#include "kselftest.h"
#define MB (1024 * 1024)
@@ -183,6 +184,7 @@ void mem_flush(unsigned char *buf, size_t buf_size);
void fill_cache_read(unsigned char *buf, size_t buf_size, bool once);
ssize_t get_fill_buf_size(int cpu_no, const char *cache_type);
int initialize_read_mem_bw_imc(void);
+void cleanup_read_mem_bw_imc(void);
int measure_read_mem_bw(const struct user_params *uparams,
struct resctrl_val_param *param, pid_t bm_pid);
void initialize_mem_bw_resctrl(const struct resctrl_val_param *param,
diff --git a/tools/testing/selftests/resctrl/resctrl_val.c b/tools/testing/selftests/resctrl/resctrl_val.c
index f20d2194c35f..7e7d0f9cc249 100644
--- a/tools/testing/selftests/resctrl/resctrl_val.c
+++ b/tools/testing/selftests/resctrl/resctrl_val.c
@@ -14,7 +14,6 @@
#define READ_FILE_NAME "cas_count_read"
#define DYN_PMU_PATH "/sys/bus/event_source/devices"
#define SCALE 0.00006103515625
-#define MAX_IMCS 40
#define MAX_TOKENS 5
#define CON_MBM_LOCAL_BYTES_PATH \
@@ -28,6 +27,7 @@ struct membw_read_format {
};
struct imc_counter_config {
+ struct list_head entry;
__u32 type;
__u64 event;
__u64 umask;
@@ -36,44 +36,40 @@ struct imc_counter_config {
};
static char mbm_total_path[1024];
-static int imcs;
-static struct imc_counter_config imc_counters_config[MAX_IMCS];
+LIST_HEAD(imc_counters_list);
static const struct resctrl_test *current_test;
-static void read_mem_bw_initialize_perf_event_attr(int i)
+static void read_mem_bw_initialize_perf_event_attr(struct imc_counter_config *imc_counter)
{
- memset(&imc_counters_config[i].pe, 0,
- sizeof(struct perf_event_attr));
- imc_counters_config[i].pe.type = imc_counters_config[i].type;
- imc_counters_config[i].pe.size = sizeof(struct perf_event_attr);
- imc_counters_config[i].pe.disabled = 1;
- imc_counters_config[i].pe.inherit = 1;
- imc_counters_config[i].pe.exclude_guest = 0;
- imc_counters_config[i].pe.config =
- imc_counters_config[i].umask << 8 |
- imc_counters_config[i].event;
- imc_counters_config[i].pe.sample_type = PERF_SAMPLE_IDENTIFIER;
- imc_counters_config[i].pe.read_format =
+ memset(&imc_counter->pe, 0, sizeof(struct perf_event_attr));
+ imc_counter->pe.type = imc_counter->type;
+ imc_counter->pe.size = sizeof(struct perf_event_attr);
+ imc_counter->pe.disabled = 1;
+ imc_counter->pe.inherit = 1;
+ imc_counter->pe.exclude_guest = 0;
+ imc_counter->pe.config = imc_counter->umask << 8 | imc_counter->event;
+ imc_counter->pe.sample_type = PERF_SAMPLE_IDENTIFIER;
+ imc_counter->pe.read_format =
PERF_FORMAT_TOTAL_TIME_ENABLED | PERF_FORMAT_TOTAL_TIME_RUNNING;
}
-static void read_mem_bw_ioctl_perf_event_ioc_reset_enable(int i)
+static void read_mem_bw_ioctl_perf_event_ioc_reset_enable(struct imc_counter_config *imc_counter)
{
- ioctl(imc_counters_config[i].fd, PERF_EVENT_IOC_RESET, 0);
- ioctl(imc_counters_config[i].fd, PERF_EVENT_IOC_ENABLE, 0);
+ ioctl(imc_counter->fd, PERF_EVENT_IOC_RESET, 0);
+ ioctl(imc_counter->fd, PERF_EVENT_IOC_ENABLE, 0);
}
-static void read_mem_bw_ioctl_perf_event_ioc_disable(int i)
+static void read_mem_bw_ioctl_perf_event_ioc_disable(struct imc_counter_config *imc_counter)
{
- ioctl(imc_counters_config[i].fd, PERF_EVENT_IOC_DISABLE, 0);
+ ioctl(imc_counter->fd, PERF_EVENT_IOC_DISABLE, 0);
}
/*
* get_read_event_and_umask: Parse config into event and umask
* @cas_count_cfg: Config
- * @count: iMC number
+ * @imc_counter: iMC counter config
*/
-static void get_read_event_and_umask(char *cas_count_cfg, unsigned int count)
+static void get_read_event_and_umask(char *cas_count_cfg, struct imc_counter_config *imc_counter)
{
char *token[MAX_TOKENS];
int i = 0;
@@ -87,21 +83,20 @@ static void get_read_event_and_umask(char *cas_count_cfg, unsigned int count)
if (!token[i])
break;
if (strcmp(token[i], "event") == 0)
- imc_counters_config[count].event = strtol(token[i + 1], NULL, 16);
+ imc_counter->event = strtol(token[i + 1], NULL, 16);
if (strcmp(token[i], "umask") == 0)
- imc_counters_config[count].umask = strtol(token[i + 1], NULL, 16);
+ imc_counter->umask = strtol(token[i + 1], NULL, 16);
}
}
-static int open_perf_read_event(int i, int cpu_no)
+static int open_perf_read_event(int cpu_no, struct imc_counter_config *imc_counter)
{
- imc_counters_config[i].fd =
- perf_event_open(&imc_counters_config[i].pe, -1, cpu_no, -1,
- PERF_FLAG_FD_CLOEXEC);
+ imc_counter->fd = perf_event_open(&imc_counter->pe, -1, cpu_no, -1,
+ PERF_FLAG_FD_CLOEXEC);
- if (imc_counters_config[i].fd == -1) {
+ if (imc_counter->fd == -1) {
fprintf(stderr, "Error opening leader %llx\n",
- imc_counters_config[i].pe.config);
+ imc_counter->pe.config);
return -1;
}
@@ -109,11 +104,11 @@ static int open_perf_read_event(int i, int cpu_no)
return 0;
}
-static int parse_imc_read_bw_events(char *imc_dir, unsigned int type,
- unsigned int *count)
+static int parse_imc_read_bw_events(char *imc_dir, unsigned int type)
{
char imc_events_dir[PATH_MAX], imc_counter_cfg[PATH_MAX];
- unsigned int orig_count = *count;
+ struct imc_counter_config *imc_counter;
+ bool found_event = false;
char cas_count_cfg[1024];
struct dirent *ep;
int path_len;
@@ -126,13 +121,13 @@ static int parse_imc_read_bw_events(char *imc_dir, unsigned int type,
imc_dir);
if (path_len >= sizeof(imc_events_dir)) {
ksft_print_msg("Unable to create path to %sevents\n", imc_dir);
- return -1;
+ goto out;
}
dp = opendir(imc_events_dir);
if (!dp) {
ksft_perror("Unable to open PMU events directory");
- return -1;
+ goto out;
}
while ((ep = readdir(dp))) {
@@ -163,28 +158,33 @@ static int parse_imc_read_bw_events(char *imc_dir, unsigned int type,
ksft_perror("Could not get iMC cas count read");
goto out_close;
}
- if (*count >= MAX_IMCS) {
- ksft_print_msg("Maximum iMC count exceeded\n");
+ imc_counter = calloc(1, sizeof(*imc_counter));
+ if (!imc_counter) {
+ ksft_perror("Unable to allocate memory for iMC counters");
goto out_close;
}
- imc_counters_config[*count].type = type;
- get_read_event_and_umask(cas_count_cfg, *count);
- /* Do not fail after incrementing *count. */
- *count += 1;
+ imc_counter->type = type;
+ get_read_event_and_umask(cas_count_cfg, imc_counter);
+ list_add(&imc_counter->entry, &imc_counters_list);
+ found_event = true;
}
- if (*count == orig_count) {
+ if (!found_event) {
ksft_print_msg("Unable to find events in %s\n", imc_events_dir);
goto out_close;
}
ret = 0;
out_close:
closedir(dp);
+out:
+ if (ret)
+ cleanup_read_mem_bw_imc();
+
return ret;
}
/* Get type and config of an iMC counter's read event. */
-static int read_from_imc_dir(char *imc_dir, unsigned int *count)
+static int read_from_imc_dir(char *imc_dir)
{
char imc_counter_type[PATH_MAX];
unsigned int type;
@@ -212,7 +212,7 @@ static int read_from_imc_dir(char *imc_dir, unsigned int *count)
ksft_perror("Could not get iMC type");
return -1;
}
- ret = parse_imc_read_bw_events(imc_dir, type, count);
+ ret = parse_imc_read_bw_events(imc_dir, type);
if (ret) {
ksft_print_msg("Unable to parse bandwidth event and umask\n");
return ret;
@@ -222,21 +222,18 @@ static int read_from_imc_dir(char *imc_dir, unsigned int *count)
}
/*
- * A system can have 'n' number of iMC (Integrated Memory Controller)
- * counters, get that 'n'. Discover the properties of the available
- * counters in support of needed performance measurement via perf.
- * For each iMC counter get it's type and config. Also obtain each
- * counter's event and umask for the memory read events that will be
- * measured.
+ * Discover the properties of the available iMC (Integrated Memory Controller)
+ * counters in support of needed performance measurement via perf. For each iMC
+ * counter get it's type and config. Also obtain each counter's event and umask
+ * for the memory read events that will be measured.
*
- * Enumerate all these details into an array of structures.
+ * Enumerate all these details into a linked list of structures.
*
* Return: >= 0 on success. < 0 on failure.
*/
-static int num_of_imcs(void)
+static int enumerate_imcs(void)
{
char imc_dir[512], *temp;
- unsigned int count = 0;
struct dirent *ep;
int ret;
DIR *dp;
@@ -265,7 +262,7 @@ static int num_of_imcs(void)
if (temp[0] >= '0' && temp[0] <= '9') {
sprintf(imc_dir, "%s/%s/", DYN_PMU_PATH,
ep->d_name);
- ret = read_from_imc_dir(imc_dir, &count);
+ ret = read_from_imc_dir(imc_dir);
if (ret) {
closedir(dp);
@@ -274,7 +271,7 @@ static int num_of_imcs(void)
}
}
closedir(dp);
- if (count == 0) {
+ if (list_empty(&imc_counters_list)) {
ksft_print_msg("Unable to find iMC counters\n");
return -1;
@@ -285,31 +282,42 @@ static int num_of_imcs(void)
return -1;
}
- return count;
+ return 0;
}
int initialize_read_mem_bw_imc(void)
{
- int imc;
+ struct imc_counter_config *imc_counter;
+ int ret;
- imcs = num_of_imcs();
- if (imcs <= 0)
- return imcs;
+ ret = enumerate_imcs();
+ if (ret < 0)
+ return ret;
/* Initialize perf_event_attr structures for all iMC's */
- for (imc = 0; imc < imcs; imc++)
- read_mem_bw_initialize_perf_event_attr(imc);
+ list_for_each_entry(imc_counter, &imc_counters_list, entry)
+ read_mem_bw_initialize_perf_event_attr(imc_counter);
return 0;
}
+void cleanup_read_mem_bw_imc(void)
+{
+ struct imc_counter_config *imc_counter, *tmp;
+
+ list_for_each_entry_safe(imc_counter, tmp, &imc_counters_list, entry) {
+ list_del(&imc_counter->entry);
+ free(imc_counter);
+ }
+}
+
static void perf_close_imc_read_mem_bw(void)
{
- int mc;
+ struct imc_counter_config *imc_counter;
- for (mc = 0; mc < imcs; mc++) {
- if (imc_counters_config[mc].fd != -1)
- close(imc_counters_config[mc].fd);
+ list_for_each_entry(imc_counter, &imc_counters_list, entry) {
+ if (imc_counter->fd != -1)
+ close(imc_counter->fd);
}
}
@@ -321,13 +329,14 @@ static void perf_close_imc_read_mem_bw(void)
*/
static int perf_open_imc_read_mem_bw(int cpu_no)
{
- int imc, ret;
+ struct imc_counter_config *imc_counter;
+ int ret;
- for (imc = 0; imc < imcs; imc++)
- imc_counters_config[imc].fd = -1;
+ list_for_each_entry(imc_counter, &imc_counters_list, entry)
+ imc_counter->fd = -1;
- for (imc = 0; imc < imcs; imc++) {
- ret = open_perf_read_event(imc, cpu_no);
+ list_for_each_entry(imc_counter, &imc_counters_list, entry) {
+ ret = open_perf_read_event(cpu_no, imc_counter);
if (ret)
goto close_fds;
}
@@ -347,16 +356,16 @@ static int perf_open_imc_read_mem_bw(int cpu_no)
*/
static void do_imc_read_mem_bw_test(void)
{
- int imc;
+ struct imc_counter_config *imc_counter;
- for (imc = 0; imc < imcs; imc++)
- read_mem_bw_ioctl_perf_event_ioc_reset_enable(imc);
+ list_for_each_entry(imc_counter, &imc_counters_list, entry)
+ read_mem_bw_ioctl_perf_event_ioc_reset_enable(imc_counter);
sleep(1);
/* Stop counters after a second to get results. */
- for (imc = 0; imc < imcs; imc++)
- read_mem_bw_ioctl_perf_event_ioc_disable(imc);
+ list_for_each_entry(imc_counter, &imc_counters_list, entry)
+ read_mem_bw_ioctl_perf_event_ioc_disable(imc_counter);
}
/*
@@ -371,17 +380,15 @@ static void do_imc_read_mem_bw_test(void)
static int get_read_mem_bw_imc(float *bw_imc)
{
float reads = 0, of_mul_read = 1;
- int imc;
+ struct imc_counter_config *r;
/*
* Log read event values from all iMC counters into
* struct imc_counter_config.
* Take overflow into consideration before calculating total bandwidth.
*/
- for (imc = 0; imc < imcs; imc++) {
+ list_for_each_entry(r, &imc_counters_list, entry) {
struct membw_read_format measurement;
- struct imc_counter_config *r =
- &imc_counters_config[imc];
if (read(r->fd, &measurement, sizeof(measurement)) == -1) {
ksft_perror("Couldn't get read bandwidth through iMC");
reply other threads:[~2026-10-21 19:34 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
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=4017e436-9f32-4cdb-a75d-4cbfcddd69f4@linuxfoundation.org \
--to=skhan@linuxfoundation.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-kselftest@vger.kernel.org \
--cc=shuah@kernel.org \
--cc=torvalds@linux-foundation.org \
/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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®