Commit 7dc0e9c7 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'linux_kselftest-next-6.7-rc1' of...

Merge tag 'linux_kselftest-next-6.7-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/shuah/linux-kselftest

Pull kselftest updates from Shuah Khan:

 - kbuild kselftest-merge target fixes

 - fixes to several tests

 - resctrl test fixes and enhancements

 - ksft_perror() helper and reporting improvements

 - printf attribute to kselftest prints to improve reporting

 - documentation and clang build warning fixes

The bulk of the patches are for resctrl fixes and enhancements.

* tag 'linux_kselftest-next-6.7-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/shuah/linux-kselftest: (51 commits)
  selftests/resctrl: Fix MBM test failure when MBA unavailable
  selftests/clone3: Report descriptive test names
  selftests:modify the incorrect print format
  selftests/efivarfs: create-read: fix a resource leak
  selftests/ftrace: Add riscv support for kprobe arg tests
  selftests/ftrace: add loongarch support for kprobe args char tests
  selftests/amd-pstate: Added option to provide perf binary path
  selftests/amd-pstate: Fix broken paths to run workloads in amd-pstate-ut
  selftests/resctrl: Move run_benchmark() to a more fitting file
  selftests/resctrl: Fix schemata write error check
  selftests/resctrl: Reduce failures due to outliers in MBA/MBM tests
  selftests/resctrl: Fix feature checks
  selftests/resctrl: Refactor feature check to use resource and feature name
  selftests/resctrl: Move _GNU_SOURCE define into Makefile
  selftests/resctrl: Remove duplicate feature check from CMT test
  selftests/resctrl: Extend signal handler coverage to unmount on receiving signal
  selftests/resctrl: Fix uninitialized .sa_flags
  selftests/resctrl: Cleanup benchmark argument parsing
  selftests/resctrl: Remove ben_count variable
  selftests/resctrl: Make benchmark command const and build it with pointers
  ...
parents 5eda8f25 5247e6db
...@@ -112,7 +112,7 @@ You can specify multiple tests to skip:: ...@@ -112,7 +112,7 @@ You can specify multiple tests to skip::
You can also specify a restricted list of tests to run together with a You can also specify a restricted list of tests to run together with a
dedicated skiplist:: dedicated skiplist::
$ make TARGETS="bpf breakpoints size timers" SKIP_TARGETS=bpf kselftest $ make TARGETS="breakpoints size timers" SKIP_TARGETS=size kselftest
See the top-level tools/testing/selftests/Makefile for the list of all See the top-level tools/testing/selftests/Makefile for the list of all
possible targets. possible targets.
...@@ -165,7 +165,7 @@ To see the list of available tests, the `-l` option can be used:: ...@@ -165,7 +165,7 @@ To see the list of available tests, the `-l` option can be used::
The `-c` option can be used to run all the tests from a test collection, or The `-c` option can be used to run all the tests from a test collection, or
the `-t` option for specific single tests. Either can be used multiple times:: the `-t` option for specific single tests. Either can be used multiple times::
$ ./run_kselftest.sh -c bpf -c seccomp -t timers:posix_timers -t timer:nanosleep $ ./run_kselftest.sh -c size -c seccomp -t timers:posix_timers -t timer:nanosleep
For other features see the script usage output, seen with the `-h` option. For other features see the script usage output, seen with the `-h` option.
...@@ -210,7 +210,7 @@ option is supported, such as:: ...@@ -210,7 +210,7 @@ option is supported, such as::
tests by using variables specified in `Running a subset of selftests`_ tests by using variables specified in `Running a subset of selftests`_
section:: section::
$ make -C tools/testing/selftests gen_tar TARGETS="bpf" FORMAT=.xz $ make -C tools/testing/selftests gen_tar TARGETS="size" FORMAT=.xz
.. _tar's auto-compress: https://www.gnu.org/software/tar/manual/html_node/gzip.html#auto_002dcompress .. _tar's auto-compress: https://www.gnu.org/software/tar/manual/html_node/gzip.html#auto_002dcompress
......
...@@ -1367,8 +1367,8 @@ kselftest-%: headers FORCE ...@@ -1367,8 +1367,8 @@ kselftest-%: headers FORCE
PHONY += kselftest-merge PHONY += kselftest-merge
kselftest-merge: kselftest-merge:
$(if $(wildcard $(objtree)/.config),, $(error No .config exists, config your kernel first!)) $(if $(wildcard $(objtree)/.config),, $(error No .config exists, config your kernel first!))
$(Q)find $(srctree)/tools/testing/selftests -name config | \ $(Q)find $(srctree)/tools/testing/selftests -name config -o -name config.$(UTS_MACHINE) | \
xargs $(srctree)/scripts/kconfig/merge_config.sh -m $(objtree)/.config xargs $(srctree)/scripts/kconfig/merge_config.sh -y -m $(objtree)/.config
$(Q)$(MAKE) -f $(srctree)/Makefile olddefconfig $(Q)$(MAKE) -f $(srctree)/Makefile olddefconfig
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
......
...@@ -30,8 +30,7 @@ import getopt ...@@ -30,8 +30,7 @@ import getopt
import Gnuplot import Gnuplot
from numpy import * from numpy import *
from decimal import * from decimal import *
sys.path.append('../intel_pstate_tracer') sys.path.append(os.path.join(os.path.dirname(__file__), "..", "intel_pstate_tracer"))
#import intel_pstate_tracer
import intel_pstate_tracer as ipt import intel_pstate_tracer as ipt
__license__ = "GPL version 2" __license__ = "GPL version 2"
......
#!/bin/sh #!/bin/bash
# SPDX-License-Identifier: GPL-2.0 # SPDX-License-Identifier: GPL-2.0
# Testing and monitor the cpu desire performance, frequency, load, # Testing and monitor the cpu desire performance, frequency, load,
...@@ -66,12 +66,15 @@ post_clear_gitsource() ...@@ -66,12 +66,15 @@ post_clear_gitsource()
install_gitsource() install_gitsource()
{ {
if [ ! -d $git_name ]; then if [ ! -d $SCRIPTDIR/$git_name ]; then
pushd $(pwd) > /dev/null 2>&1
cd $SCRIPTDIR
printf "Download gitsource, please wait a moment ...\n\n" printf "Download gitsource, please wait a moment ...\n\n"
wget -O $git_tar $gitsource_url > /dev/null 2>&1 wget -O $git_tar $gitsource_url > /dev/null 2>&1
printf "Tar gitsource ...\n\n" printf "Tar gitsource ...\n\n"
tar -xzf $git_tar tar -xzf $git_tar
popd > /dev/null 2>&1
fi fi
} }
...@@ -79,12 +82,14 @@ install_gitsource() ...@@ -79,12 +82,14 @@ install_gitsource()
run_gitsource() run_gitsource()
{ {
echo "Launching amd pstate tracer for $1 #$2 tracer_interval: $TRACER_INTERVAL" echo "Launching amd pstate tracer for $1 #$2 tracer_interval: $TRACER_INTERVAL"
./amd_pstate_trace.py -n tracer-gitsource-$1-$2 -i $TRACER_INTERVAL > /dev/null 2>&1 & $TRACER -n tracer-gitsource-$1-$2 -i $TRACER_INTERVAL > /dev/null 2>&1 &
printf "Make and test gitsource for $1 #$2 make_cpus: $MAKE_CPUS\n" printf "Make and test gitsource for $1 #$2 make_cpus: $MAKE_CPUS\n"
cd $git_name BACKUP_DIR=$(pwd)
perf stat -a --per-socket -I 1000 -e power/energy-pkg/ /usr/bin/time -o ../$OUTFILE_GIT.time-gitsource-$1-$2.log make test -j$MAKE_CPUS > ../$OUTFILE_GIT-perf-$1-$2.log 2>&1 pushd $BACKUP_DIR > /dev/null 2>&1
cd .. cd $SCRIPTDIR/$git_name
$PERF stat -a --per-socket -I 1000 -e power/energy-pkg/ /usr/bin/time -o $BACKUP_DIR/$OUTFILE_GIT.time-gitsource-$1-$2.log make test -j$MAKE_CPUS > $BACKUP_DIR/$OUTFILE_GIT-perf-$1-$2.log 2>&1
popd > /dev/null 2>&1
for job in `jobs -p` for job in `jobs -p`
do do
......
...@@ -8,9 +8,12 @@ else ...@@ -8,9 +8,12 @@ else
FILE_MAIN=DONE FILE_MAIN=DONE
fi fi
source basic.sh SCRIPTDIR=`dirname "$0"`
source tbench.sh TRACER=$SCRIPTDIR/../../../power/x86/amd_pstate_tracer/amd_pstate_trace.py
source gitsource.sh
source $SCRIPTDIR/basic.sh
source $SCRIPTDIR/tbench.sh
source $SCRIPTDIR/gitsource.sh
# amd-pstate-ut only run on x86/x86_64 AMD systems. # amd-pstate-ut only run on x86/x86_64 AMD systems.
ARCH=$(uname -m 2>/dev/null | sed -e 's/i.86/x86/' -e 's/x86_64/x86/') ARCH=$(uname -m 2>/dev/null | sed -e 's/i.86/x86/' -e 's/x86_64/x86/')
...@@ -22,6 +25,7 @@ OUTFILE=selftest ...@@ -22,6 +25,7 @@ OUTFILE=selftest
OUTFILE_TBENCH="$OUTFILE.tbench" OUTFILE_TBENCH="$OUTFILE.tbench"
OUTFILE_GIT="$OUTFILE.gitsource" OUTFILE_GIT="$OUTFILE.gitsource"
PERF=/usr/bin/perf
SYSFS= SYSFS=
CPUROOT= CPUROOT=
CPUFREQROOT= CPUFREQROOT=
...@@ -151,6 +155,7 @@ help() ...@@ -151,6 +155,7 @@ help()
[-p <tbench process number>] [-p <tbench process number>]
[-l <loop times for tbench>] [-l <loop times for tbench>]
[-i <amd tracer interval>] [-i <amd tracer interval>]
[-b <perf binary>]
[-m <comparative test: acpi-cpufreq>] [-m <comparative test: acpi-cpufreq>]
\n" \n"
exit 2 exit 2
...@@ -158,7 +163,7 @@ help() ...@@ -158,7 +163,7 @@ help()
parse_arguments() parse_arguments()
{ {
while getopts ho:c:t:p:l:i:m: arg while getopts ho:c:t:p:l:i:b:m: arg
do do
case $arg in case $arg in
h) # --help h) # --help
...@@ -189,6 +194,10 @@ parse_arguments() ...@@ -189,6 +194,10 @@ parse_arguments()
TRACER_INTERVAL=$OPTARG TRACER_INTERVAL=$OPTARG
;; ;;
b) # --perf-binary
PERF=`realpath $OPTARG`
;;
m) # --comparative-test m) # --comparative-test
COMPARATIVE_TEST=$OPTARG COMPARATIVE_TEST=$OPTARG
;; ;;
...@@ -202,8 +211,8 @@ parse_arguments() ...@@ -202,8 +211,8 @@ parse_arguments()
command_perf() command_perf()
{ {
if ! command -v perf > /dev/null; then if ! $PERF -v; then
echo $msg please install perf. >&2 echo $msg please install perf or provide perf binary path as argument >&2
exit $ksft_skip exit $ksft_skip
fi fi
} }
......
...@@ -64,11 +64,11 @@ post_clear_tbench() ...@@ -64,11 +64,11 @@ post_clear_tbench()
run_tbench() run_tbench()
{ {
echo "Launching amd pstate tracer for $1 #$2 tracer_interval: $TRACER_INTERVAL" echo "Launching amd pstate tracer for $1 #$2 tracer_interval: $TRACER_INTERVAL"
./amd_pstate_trace.py -n tracer-tbench-$1-$2 -i $TRACER_INTERVAL > /dev/null 2>&1 & $TRACER -n tracer-tbench-$1-$2 -i $TRACER_INTERVAL > /dev/null 2>&1 &
printf "Test tbench for $1 #$2 time_limit: $TIME_LIMIT procs_num: $PROCESS_NUM\n" printf "Test tbench for $1 #$2 time_limit: $TIME_LIMIT procs_num: $PROCESS_NUM\n"
tbench_srv > /dev/null 2>&1 & tbench_srv > /dev/null 2>&1 &
perf stat -a --per-socket -I 1000 -e power/energy-pkg/ tbench -t $TIME_LIMIT $PROCESS_NUM > $OUTFILE_TBENCH-perf-$1-$2.log 2>&1 $PERF stat -a --per-socket -I 1000 -e power/energy-pkg/ tbench -t $TIME_LIMIT $PROCESS_NUM > $OUTFILE_TBENCH-perf-$1-$2.log 2>&1
pid=`pidof tbench_srv` pid=`pidof tbench_srv`
kill $pid kill $pid
......
...@@ -27,7 +27,7 @@ static const char * const dev_files[] = { ...@@ -27,7 +27,7 @@ static const char * const dev_files[] = {
void print_cachestat(struct cachestat *cs) void print_cachestat(struct cachestat *cs)
{ {
ksft_print_msg( ksft_print_msg(
"Using cachestat: Cached: %lu, Dirty: %lu, Writeback: %lu, Evicted: %lu, Recently Evicted: %lu\n", "Using cachestat: Cached: %llu, Dirty: %llu, Writeback: %llu, Evicted: %llu, Recently Evicted: %llu\n",
cs->nr_cache, cs->nr_dirty, cs->nr_writeback, cs->nr_cache, cs->nr_dirty, cs->nr_writeback,
cs->nr_evicted, cs->nr_recently_evicted); cs->nr_evicted, cs->nr_recently_evicted);
} }
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
TEST_GEN_FILES := validate_cap TEST_GEN_FILES := validate_cap
TEST_GEN_PROGS := test_execve TEST_GEN_PROGS := test_execve
CFLAGS += -O2 -g -std=gnu99 -Wall CFLAGS += -O2 -g -std=gnu99 -Wall $(KHDR_INCLUDES)
LDLIBS += -lcap-ng -lrt -ldl LDLIBS += -lcap-ng -lrt -ldl
include ../lib.mk include ../lib.mk
......
...@@ -20,14 +20,6 @@ ...@@ -20,14 +20,6 @@
#include "../kselftest.h" #include "../kselftest.h"
#ifndef PR_CAP_AMBIENT
#define PR_CAP_AMBIENT 47
# define PR_CAP_AMBIENT_IS_SET 1
# define PR_CAP_AMBIENT_RAISE 2
# define PR_CAP_AMBIENT_LOWER 3
# define PR_CAP_AMBIENT_CLEAR_ALL 4
#endif
static int nerrs; static int nerrs;
static pid_t mpid; /* main() pid is used to avoid duplicate test counts */ static pid_t mpid; /* main() pid is used to avoid duplicate test counts */
......
...@@ -9,14 +9,6 @@ ...@@ -9,14 +9,6 @@
#include "../kselftest.h" #include "../kselftest.h"
#ifndef PR_CAP_AMBIENT
#define PR_CAP_AMBIENT 47
# define PR_CAP_AMBIENT_IS_SET 1
# define PR_CAP_AMBIENT_RAISE 2
# define PR_CAP_AMBIENT_LOWER 3
# define PR_CAP_AMBIENT_CLEAR_ALL 4
#endif
#if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 19) #if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 19)
# define HAVE_GETAUXVAL # define HAVE_GETAUXVAL
#endif #endif
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include <inttypes.h> #include <inttypes.h>
#include <linux/types.h> #include <linux/types.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <stdbool.h>
#include <stdint.h> #include <stdint.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
...@@ -103,7 +104,7 @@ static int call_clone3(uint64_t flags, size_t size, enum test_mode test_mode) ...@@ -103,7 +104,7 @@ static int call_clone3(uint64_t flags, size_t size, enum test_mode test_mode)
return 0; return 0;
} }
static void test_clone3(uint64_t flags, size_t size, int expected, static bool test_clone3(uint64_t flags, size_t size, int expected,
enum test_mode test_mode) enum test_mode test_mode)
{ {
int ret; int ret;
...@@ -114,92 +115,210 @@ static void test_clone3(uint64_t flags, size_t size, int expected, ...@@ -114,92 +115,210 @@ static void test_clone3(uint64_t flags, size_t size, int expected,
ret = call_clone3(flags, size, test_mode); ret = call_clone3(flags, size, test_mode);
ksft_print_msg("[%d] clone3() with flags says: %d expected %d\n", ksft_print_msg("[%d] clone3() with flags says: %d expected %d\n",
getpid(), ret, expected); getpid(), ret, expected);
if (ret != expected) if (ret != expected) {
ksft_test_result_fail( ksft_print_msg(
"[%d] Result (%d) is different than expected (%d)\n", "[%d] Result (%d) is different than expected (%d)\n",
getpid(), ret, expected); getpid(), ret, expected);
else return false;
ksft_test_result_pass( }
"[%d] Result (%d) matches expectation (%d)\n",
getpid(), ret, expected);
}
int main(int argc, char *argv[])
{
uid_t uid = getuid();
ksft_print_header();
ksft_set_plan(19);
test_clone3_supported();
/* Just a simple clone3() should return 0.*/
test_clone3(0, 0, 0, CLONE3_ARGS_NO_TEST);
/* Do a clone3() in a new PID NS.*/
if (uid == 0)
test_clone3(CLONE_NEWPID, 0, 0, CLONE3_ARGS_NO_TEST);
else
ksft_test_result_skip("Skipping clone3() with CLONE_NEWPID\n");
/* Do a clone3() with CLONE_ARGS_SIZE_VER0. */
test_clone3(0, CLONE_ARGS_SIZE_VER0, 0, CLONE3_ARGS_NO_TEST);
/* Do a clone3() with CLONE_ARGS_SIZE_VER0 - 8 */
test_clone3(0, CLONE_ARGS_SIZE_VER0 - 8, -EINVAL, CLONE3_ARGS_NO_TEST);
/* Do a clone3() with sizeof(struct clone_args) + 8 */
test_clone3(0, sizeof(struct __clone_args) + 8, 0, CLONE3_ARGS_NO_TEST);
/* Do a clone3() with exit_signal having highest 32 bits non-zero */ return true;
test_clone3(0, 0, -EINVAL, CLONE3_ARGS_INVAL_EXIT_SIGNAL_BIG); }
/* Do a clone3() with negative 32-bit exit_signal */ typedef bool (*filter_function)(void);
test_clone3(0, 0, -EINVAL, CLONE3_ARGS_INVAL_EXIT_SIGNAL_NEG); typedef size_t (*size_function)(void);
/* Do a clone3() with exit_signal not fitting into CSIGNAL mask */ static bool not_root(void)
test_clone3(0, 0, -EINVAL, CLONE3_ARGS_INVAL_EXIT_SIGNAL_CSIG); {
if (getuid() != 0) {
ksft_print_msg("Not running as root\n");
return true;
}
/* Do a clone3() with NSIG < exit_signal < CSIG */ return false;
test_clone3(0, 0, -EINVAL, CLONE3_ARGS_INVAL_EXIT_SIGNAL_NSIG); }
test_clone3(0, sizeof(struct __clone_args) + 8, 0, CLONE3_ARGS_ALL_0); static size_t page_size_plus_8(void)
{
return getpagesize() + 8;
}
test_clone3(0, sizeof(struct __clone_args) + 16, -E2BIG, struct test {
CLONE3_ARGS_ALL_0); const char *name;
uint64_t flags;
size_t size;
size_function size_function;
int expected;
enum test_mode test_mode;
filter_function filter;
};
test_clone3(0, sizeof(struct __clone_args) * 2, -E2BIG, static const struct test tests[] = {
CLONE3_ARGS_ALL_0); {
.name = "simple clone3()",
.flags = 0,
.size = 0,
.expected = 0,
.test_mode = CLONE3_ARGS_NO_TEST,
},
{
.name = "clone3() in a new PID_NS",
.flags = CLONE_NEWPID,
.size = 0,
.expected = 0,
.test_mode = CLONE3_ARGS_NO_TEST,
.filter = not_root,
},
{
.name = "CLONE_ARGS_SIZE_VER0",
.flags = 0,
.size = CLONE_ARGS_SIZE_VER0,
.expected = 0,
.test_mode = CLONE3_ARGS_NO_TEST,
},
{
.name = "CLONE_ARGS_SIZE_VER0 - 8",
.flags = 0,
.size = CLONE_ARGS_SIZE_VER0 - 8,
.expected = -EINVAL,
.test_mode = CLONE3_ARGS_NO_TEST,
},
{
.name = "sizeof(struct clone_args) + 8",
.flags = 0,
.size = sizeof(struct __clone_args) + 8,
.expected = 0,
.test_mode = CLONE3_ARGS_NO_TEST,
},
{
.name = "exit_signal with highest 32 bits non-zero",
.flags = 0,
.size = 0,
.expected = -EINVAL,
.test_mode = CLONE3_ARGS_INVAL_EXIT_SIGNAL_BIG,
},
{
.name = "negative 32-bit exit_signal",
.flags = 0,
.size = 0,
.expected = -EINVAL,
.test_mode = CLONE3_ARGS_INVAL_EXIT_SIGNAL_NEG,
},
{
.name = "exit_signal not fitting into CSIGNAL mask",
.flags = 0,
.size = 0,
.expected = -EINVAL,
.test_mode = CLONE3_ARGS_INVAL_EXIT_SIGNAL_CSIG,
},
{
.name = "NSIG < exit_signal < CSIG",
.flags = 0,
.size = 0,
.expected = -EINVAL,
.test_mode = CLONE3_ARGS_INVAL_EXIT_SIGNAL_NSIG,
},
{
.name = "Arguments sizeof(struct clone_args) + 8",
.flags = 0,
.size = sizeof(struct __clone_args) + 8,
.expected = 0,
.test_mode = CLONE3_ARGS_ALL_0,
},
{
.name = "Arguments sizeof(struct clone_args) + 16",
.flags = 0,
.size = sizeof(struct __clone_args) + 16,
.expected = -E2BIG,
.test_mode = CLONE3_ARGS_ALL_0,
},
{
.name = "Arguments sizeof(struct clone_arg) * 2",
.flags = 0,
.size = sizeof(struct __clone_args) + 16,
.expected = -E2BIG,
.test_mode = CLONE3_ARGS_ALL_0,
},
{
.name = "Arguments > page size",
.flags = 0,
.size_function = page_size_plus_8,
.expected = -E2BIG,
.test_mode = CLONE3_ARGS_NO_TEST,
},
{
.name = "CLONE_ARGS_SIZE_VER0 in a new PID NS",
.flags = CLONE_NEWPID,
.size = CLONE_ARGS_SIZE_VER0,
.expected = 0,
.test_mode = CLONE3_ARGS_NO_TEST,
.filter = not_root,
},
{
.name = "CLONE_ARGS_SIZE_VER0 - 8 in a new PID NS",
.flags = CLONE_NEWPID,
.size = CLONE_ARGS_SIZE_VER0 - 8,
.expected = -EINVAL,
.test_mode = CLONE3_ARGS_NO_TEST,
},
{
.name = "sizeof(struct clone_args) + 8 in a new PID NS",
.flags = CLONE_NEWPID,
.size = sizeof(struct __clone_args) + 8,
.expected = 0,
.test_mode = CLONE3_ARGS_NO_TEST,
.filter = not_root,
},
{
.name = "Arguments > page size in a new PID NS",
.flags = CLONE_NEWPID,
.size_function = page_size_plus_8,
.expected = -E2BIG,
.test_mode = CLONE3_ARGS_NO_TEST,
},
{
.name = "New time NS",
.flags = CLONE_NEWTIME,
.size = 0,
.expected = 0,
.test_mode = CLONE3_ARGS_NO_TEST,
},
{
.name = "exit signal (SIGCHLD) in flags",
.flags = SIGCHLD,
.size = 0,
.expected = -EINVAL,
.test_mode = CLONE3_ARGS_NO_TEST,
},
};
/* Do a clone3() with > page size */ int main(int argc, char *argv[])
test_clone3(0, getpagesize() + 8, -E2BIG, CLONE3_ARGS_NO_TEST); {
size_t size;
int i;
/* Do a clone3() with CLONE_ARGS_SIZE_VER0 in a new PID NS. */ ksft_print_header();
if (uid == 0) ksft_set_plan(ARRAY_SIZE(tests));
test_clone3(CLONE_NEWPID, CLONE_ARGS_SIZE_VER0, 0, test_clone3_supported();
CLONE3_ARGS_NO_TEST);
else
ksft_test_result_skip("Skipping clone3() with CLONE_NEWPID\n");
/* Do a clone3() with CLONE_ARGS_SIZE_VER0 - 8 in a new PID NS */ for (i = 0; i < ARRAY_SIZE(tests); i++) {
test_clone3(CLONE_NEWPID, CLONE_ARGS_SIZE_VER0 - 8, -EINVAL, if (tests[i].filter && tests[i].filter()) {
CLONE3_ARGS_NO_TEST); ksft_test_result_skip("%s\n", tests[i].name);
continue;
}
/* Do a clone3() with sizeof(struct clone_args) + 8 in a new PID NS */ if (tests[i].size_function)
if (uid == 0) size = tests[i].size_function();
test_clone3(CLONE_NEWPID, sizeof(struct __clone_args) + 8, 0,
CLONE3_ARGS_NO_TEST);
else else
ksft_test_result_skip("Skipping clone3() with CLONE_NEWPID\n"); size = tests[i].size;
/* Do a clone3() with > page size in a new PID NS */ ksft_print_msg("Running test '%s'\n", tests[i].name);
test_clone3(CLONE_NEWPID, getpagesize() + 8, -E2BIG,
CLONE3_ARGS_NO_TEST);
/* Do a clone3() in a new time namespace */ ksft_test_result(test_clone3(tests[i].flags, size,
test_clone3(CLONE_NEWTIME, 0, 0, CLONE3_ARGS_NO_TEST); tests[i].expected,
tests[i].test_mode),
/* Do a clone3() with exit signal (SIGCHLD) in flags */ "%s\n", tests[i].name);
test_clone3(SIGCHLD, 0, -EINVAL, CLONE3_ARGS_NO_TEST); }
ksft_finished(); ksft_finished();
} }
...@@ -27,9 +27,7 @@ ...@@ -27,9 +27,7 @@
#include "../kselftest_harness.h" #include "../kselftest_harness.h"
#include "clone3_selftests.h" #include "clone3_selftests.h"
#ifndef MAX_PID_NS_LEVEL
#define MAX_PID_NS_LEVEL 32 #define MAX_PID_NS_LEVEL 32
#endif
static void child_exit(int ret) static void child_exit(int ret)
{ {
......
...@@ -16,10 +16,6 @@ ...@@ -16,10 +16,6 @@
#include "../kselftest.h" #include "../kselftest.h"
#include "clone3_selftests.h" #include "clone3_selftests.h"
#ifndef CLONE_CLEAR_SIGHAND
#define CLONE_CLEAR_SIGHAND 0x100000000ULL
#endif
static void nop_handler(int signo) static void nop_handler(int signo)
{ {
} }
......
...@@ -15,10 +15,6 @@ ...@@ -15,10 +15,6 @@
#define ptr_to_u64(ptr) ((__u64)((uintptr_t)(ptr))) #define ptr_to_u64(ptr) ((__u64)((uintptr_t)(ptr)))
#ifndef CLONE_INTO_CGROUP
#define CLONE_INTO_CGROUP 0x200000000ULL /* Clone into a specific cgroup given the right permissions. */
#endif
#ifndef __NR_clone3 #ifndef __NR_clone3
#define __NR_clone3 -1 #define __NR_clone3 -1
#endif #endif
...@@ -32,18 +28,9 @@ struct __clone_args { ...@@ -32,18 +28,9 @@ struct __clone_args {
__aligned_u64 stack; __aligned_u64 stack;
__aligned_u64 stack_size; __aligned_u64 stack_size;
__aligned_u64 tls; __aligned_u64 tls;
#ifndef CLONE_ARGS_SIZE_VER0
#define CLONE_ARGS_SIZE_VER0 64 /* sizeof first published struct */
#endif
__aligned_u64 set_tid; __aligned_u64 set_tid;
__aligned_u64 set_tid_size; __aligned_u64 set_tid_size;
#ifndef CLONE_ARGS_SIZE_VER1
#define CLONE_ARGS_SIZE_VER1 80 /* sizeof second published struct */
#endif
__aligned_u64 cgroup; __aligned_u64 cgroup;
#ifndef CLONE_ARGS_SIZE_VER2
#define CLONE_ARGS_SIZE_VER2 88 /* sizeof third published struct */
#endif
}; };
static pid_t sys_clone3(struct __clone_args *args, size_t size) static pid_t sys_clone3(struct __clone_args *args, size_t size)
......
...@@ -23,9 +23,7 @@ ...@@ -23,9 +23,7 @@
#include "../kselftest.h" #include "../kselftest.h"
#include "clone3_selftests.h" #include "clone3_selftests.h"
#ifndef MAX_PID_NS_LEVEL
#define MAX_PID_NS_LEVEL 32 #define MAX_PID_NS_LEVEL 32
#endif
static int pipe_1[2]; static int pipe_1[2];
static int pipe_2[2]; static int pipe_2[2];
......
...@@ -16,34 +16,6 @@ ...@@ -16,34 +16,6 @@
#include "../kselftest_harness.h" #include "../kselftest_harness.h"
#include "../clone3/clone3_selftests.h" #include "../clone3/clone3_selftests.h"
#ifndef __NR_close_range
#if defined __alpha__
#define __NR_close_range 546
#elif defined _MIPS_SIM
#if _MIPS_SIM == _MIPS_SIM_ABI32 /* o32 */
#define __NR_close_range (436 + 4000)
#endif
#if _MIPS_SIM == _MIPS_SIM_NABI32 /* n32 */
#define __NR_close_range (436 + 6000)
#endif
#if _MIPS_SIM == _MIPS_SIM_ABI64 /* n64 */
#define __NR_close_range (436 + 5000)
#endif
#elif defined __ia64__
#define __NR_close_range (436 + 1024)
#else
#define __NR_close_range 436
#endif
#endif
#ifndef CLOSE_RANGE_UNSHARE
#define CLOSE_RANGE_UNSHARE (1U << 1)
#endif
#ifndef CLOSE_RANGE_CLOEXEC
#define CLOSE_RANGE_CLOEXEC (1U << 2)
#endif
static inline int sys_close_range(unsigned int fd, unsigned int max_fd, static inline int sys_close_range(unsigned int fd, unsigned int max_fd,
unsigned int flags) unsigned int flags)
{ {
......
File mode changed from 100644 to 100755
File mode changed from 100644 to 100755
File mode changed from 100644 to 100755
File mode changed from 100644 to 100755
File mode changed from 100644 to 100755
File mode changed from 100644 to 100755
File mode changed from 100644 to 100755
File mode changed from 100644 to 100755
File mode changed from 100644 to 100755
File mode changed from 100644 to 100755
...@@ -32,8 +32,10 @@ int main(int argc, char **argv) ...@@ -32,8 +32,10 @@ int main(int argc, char **argv)
rc = read(fd, buf, sizeof(buf)); rc = read(fd, buf, sizeof(buf));
if (rc != 0) { if (rc != 0) {
fprintf(stderr, "Reading a new var should return EOF\n"); fprintf(stderr, "Reading a new var should return EOF\n");
close(fd);
return EXIT_FAILURE; return EXIT_FAILURE;
} }
close(fd);
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }
...@@ -23,6 +23,9 @@ ...@@ -23,6 +23,9 @@
#include "../kselftest.h" #include "../kselftest.h"
#define TESTS_EXPECTED 51
#define TEST_NAME_LEN (PATH_MAX * 4)
static char longpath[2 * PATH_MAX] = ""; static char longpath[2 * PATH_MAX] = "";
static char *envp[] = { "IN_TEST=yes", NULL, NULL }; static char *envp[] = { "IN_TEST=yes", NULL, NULL };
static char *argv[] = { "execveat", "99", NULL }; static char *argv[] = { "execveat", "99", NULL };
...@@ -43,71 +46,85 @@ static int execveat_(int fd, const char *path, char **argv, char **envp, ...@@ -43,71 +46,85 @@ static int execveat_(int fd, const char *path, char **argv, char **envp,
static int _check_execveat_fail(int fd, const char *path, int flags, static int _check_execveat_fail(int fd, const char *path, int flags,
int expected_errno, const char *errno_str) int expected_errno, const char *errno_str)
{ {
char test_name[TEST_NAME_LEN];
int rc; int rc;
errno = 0; errno = 0;
printf("Check failure of execveat(%d, '%s', %d) with %s... ", snprintf(test_name, sizeof(test_name),
"Check failure of execveat(%d, '%s', %d) with %s",
fd, path?:"(null)", flags, errno_str); fd, path?:"(null)", flags, errno_str);
rc = execveat_(fd, path, argv, envp, flags); rc = execveat_(fd, path, argv, envp, flags);
if (rc > 0) { if (rc > 0) {
printf("[FAIL] (unexpected success from execveat(2))\n"); ksft_print_msg("unexpected success from execveat(2)\n");
ksft_test_result_fail("%s\n", test_name);
return 1; return 1;
} }
if (errno != expected_errno) { if (errno != expected_errno) {
printf("[FAIL] (expected errno %d (%s) not %d (%s)\n", ksft_print_msg("expected errno %d (%s) not %d (%s)\n",
expected_errno, strerror(expected_errno), expected_errno, strerror(expected_errno),
errno, strerror(errno)); errno, strerror(errno));
ksft_test_result_fail("%s\n", test_name);
return 1; return 1;
} }
printf("[OK]\n"); ksft_test_result_pass("%s\n", test_name);
return 0; return 0;
} }
static int check_execveat_invoked_rc(int fd, const char *path, int flags, static int check_execveat_invoked_rc(int fd, const char *path, int flags,
int expected_rc, int expected_rc2) int expected_rc, int expected_rc2)
{ {
char test_name[TEST_NAME_LEN];
int status; int status;
int rc; int rc;
pid_t child; pid_t child;
int pathlen = path ? strlen(path) : 0; int pathlen = path ? strlen(path) : 0;
if (pathlen > 40) if (pathlen > 40)
printf("Check success of execveat(%d, '%.20s...%s', %d)... ", snprintf(test_name, sizeof(test_name),
"Check success of execveat(%d, '%.20s...%s', %d)... ",
fd, path, (path + pathlen - 20), flags); fd, path, (path + pathlen - 20), flags);
else else
printf("Check success of execveat(%d, '%s', %d)... ", snprintf(test_name, sizeof(test_name),
"Check success of execveat(%d, '%s', %d)... ",
fd, path?:"(null)", flags); fd, path?:"(null)", flags);
child = fork(); child = fork();
if (child < 0) { if (child < 0) {
printf("[FAIL] (fork() failed)\n"); ksft_perror("fork() failed");
ksft_test_result_fail("%s\n", test_name);
return 1; return 1;
} }
if (child == 0) { if (child == 0) {
/* Child: do execveat(). */ /* Child: do execveat(). */
rc = execveat_(fd, path, argv, envp, flags); rc = execveat_(fd, path, argv, envp, flags);
printf("[FAIL]: execveat() failed, rc=%d errno=%d (%s)\n", ksft_print_msg("execveat() failed, rc=%d errno=%d (%s)\n",
rc, errno, strerror(errno)); rc, errno, strerror(errno));
ksft_test_result_fail("%s\n", test_name);
exit(1); /* should not reach here */ exit(1); /* should not reach here */
} }
/* Parent: wait for & check child's exit status. */ /* Parent: wait for & check child's exit status. */
rc = waitpid(child, &status, 0); rc = waitpid(child, &status, 0);
if (rc != child) { if (rc != child) {
printf("[FAIL] (waitpid(%d,...) returned %d)\n", child, rc); ksft_print_msg("waitpid(%d,...) returned %d\n", child, rc);
ksft_test_result_fail("%s\n", test_name);
return 1; return 1;
} }
if (!WIFEXITED(status)) { if (!WIFEXITED(status)) {
printf("[FAIL] (child %d did not exit cleanly, status=%08x)\n", ksft_print_msg("child %d did not exit cleanly, status=%08x\n",
child, status); child, status);
ksft_test_result_fail("%s\n", test_name);
return 1; return 1;
} }
if ((WEXITSTATUS(status) != expected_rc) && if ((WEXITSTATUS(status) != expected_rc) &&
(WEXITSTATUS(status) != expected_rc2)) { (WEXITSTATUS(status) != expected_rc2)) {
printf("[FAIL] (child %d exited with %d not %d nor %d)\n", ksft_print_msg("child %d exited with %d not %d nor %d\n",
child, WEXITSTATUS(status), expected_rc, expected_rc2); child, WEXITSTATUS(status), expected_rc,
expected_rc2);
ksft_test_result_fail("%s\n", test_name);
return 1; return 1;
} }
printf("[OK]\n"); ksft_test_result_pass("%s\n", test_name);
return 0; return 0;
} }
...@@ -129,11 +146,9 @@ static int open_or_die(const char *filename, int flags) ...@@ -129,11 +146,9 @@ static int open_or_die(const char *filename, int flags)
{ {
int fd = open(filename, flags); int fd = open(filename, flags);
if (fd < 0) { if (fd < 0)
printf("Failed to open '%s'; " ksft_exit_fail_msg("Failed to open '%s'; "
"check prerequisites are available\n", filename); "check prerequisites are available\n", filename);
exit(1);
}
return fd; return fd;
} }
...@@ -162,8 +177,7 @@ static int check_execveat_pathmax(int root_dfd, const char *src, int is_script) ...@@ -162,8 +177,7 @@ static int check_execveat_pathmax(int root_dfd, const char *src, int is_script)
char *cwd = getcwd(NULL, 0); char *cwd = getcwd(NULL, 0);
if (!cwd) { if (!cwd) {
printf("Failed to getcwd(), errno=%d (%s)\n", ksft_perror("Failed to getcwd()");
errno, strerror(errno));
return 2; return 2;
} }
strcpy(longpath, cwd); strcpy(longpath, cwd);
...@@ -193,11 +207,11 @@ static int check_execveat_pathmax(int root_dfd, const char *src, int is_script) ...@@ -193,11 +207,11 @@ static int check_execveat_pathmax(int root_dfd, const char *src, int is_script)
*/ */
fd = open(longpath, O_RDONLY); fd = open(longpath, O_RDONLY);
if (fd > 0) { if (fd > 0) {
printf("Invoke copy of '%s' via filename of length %zu:\n", ksft_print_msg("Invoke copy of '%s' via filename of length %zu:\n",
src, strlen(longpath)); src, strlen(longpath));
fail += check_execveat(fd, "", AT_EMPTY_PATH); fail += check_execveat(fd, "", AT_EMPTY_PATH);
} else { } else {
printf("Failed to open length %zu filename, errno=%d (%s)\n", ksft_print_msg("Failed to open length %zu filename, errno=%d (%s)\n",
strlen(longpath), errno, strerror(errno)); strlen(longpath), errno, strerror(errno));
fail++; fail++;
} }
...@@ -405,28 +419,31 @@ int main(int argc, char **argv) ...@@ -405,28 +419,31 @@ int main(int argc, char **argv)
const char *in_test = getenv("IN_TEST"); const char *in_test = getenv("IN_TEST");
if (verbose) { if (verbose) {
printf(" invoked with:"); ksft_print_msg("invoked with:\n");
for (ii = 0; ii < argc; ii++) for (ii = 0; ii < argc; ii++)
printf(" [%d]='%s'", ii, argv[ii]); ksft_print_msg("\t[%d]='%s\n'", ii, argv[ii]);
printf("\n");
} }
/* Check expected environment transferred. */ /* Check expected environment transferred. */
if (!in_test || strcmp(in_test, "yes") != 0) { if (!in_test || strcmp(in_test, "yes") != 0) {
printf("[FAIL] (no IN_TEST=yes in env)\n"); ksft_print_msg("no IN_TEST=yes in env\n");
return 1; return 1;
} }
/* Use the final argument as an exit code. */ /* Use the final argument as an exit code. */
rc = atoi(argv[argc - 1]); rc = atoi(argv[argc - 1]);
fflush(stdout); exit(rc);
} else { } else {
ksft_print_header();
ksft_set_plan(TESTS_EXPECTED);
prerequisites(); prerequisites();
if (verbose) if (verbose)
envp[1] = "VERBOSE=1"; envp[1] = "VERBOSE=1";
rc = run_tests(); rc = run_tests();
if (rc > 0) if (rc > 0)
printf("%d tests failed\n", rc); printf("%d tests failed\n", rc);
ksft_finished();
} }
return rc; return rc;
} }
...@@ -17,10 +17,6 @@ ...@@ -17,10 +17,6 @@
#include <sys/wait.h> #include <sys/wait.h>
#include <unistd.h> #include <unistd.h>
#ifndef CLONE_NEWNS
# define CLONE_NEWNS 0x00020000
#endif
static char *fw_path = NULL; static char *fw_path = NULL;
static void die(char *fmt, ...) static void die(char *fmt, ...)
......
...@@ -28,6 +28,12 @@ s390*) ...@@ -28,6 +28,12 @@ s390*)
mips*) mips*)
ARG1=%r4 ARG1=%r4
;; ;;
loongarch*)
ARG1=%r4
;;
riscv*)
ARG1=%a0
;;
*) *)
echo "Please implement other architecture here" echo "Please implement other architecture here"
exit_untested exit_untested
......
...@@ -31,6 +31,9 @@ mips*) ...@@ -31,6 +31,9 @@ mips*)
loongarch*) loongarch*)
ARG1=%r4 ARG1=%r4
;; ;;
riscv*)
ARG1=%a0
;;
*) *)
echo "Please implement other architecture here" echo "Please implement other architecture here"
exit_untested exit_untested
......
...@@ -44,6 +44,10 @@ loongarch*) ...@@ -44,6 +44,10 @@ loongarch*)
GOODREG=%r4 GOODREG=%r4
BADREG=%r12 BADREG=%r12
;; ;;
riscv*)
GOODREG=%a0
BADREG=%a8
;;
*) *)
echo "Please implement other architecture here" echo "Please implement other architecture here"
exit_untested exit_untested
......
...@@ -48,6 +48,7 @@ ...@@ -48,6 +48,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <unistd.h> #include <unistd.h>
#include <stdarg.h> #include <stdarg.h>
#include <string.h>
#include <stdio.h> #include <stdio.h>
#endif #endif
...@@ -77,6 +78,8 @@ ...@@ -77,6 +78,8 @@
#define KSFT_XPASS 3 #define KSFT_XPASS 3
#define KSFT_SKIP 4 #define KSFT_SKIP 4
#define __printf(a, b) __attribute__((format(printf, a, b)))
/* counters */ /* counters */
struct ksft_count { struct ksft_count {
unsigned int ksft_pass; unsigned int ksft_pass;
...@@ -129,7 +132,7 @@ static inline void ksft_print_header(void) ...@@ -129,7 +132,7 @@ static inline void ksft_print_header(void)
static inline void ksft_set_plan(unsigned int plan) static inline void ksft_set_plan(unsigned int plan)
{ {
ksft_plan = plan; ksft_plan = plan;
printf("1..%d\n", ksft_plan); printf("1..%u\n", ksft_plan);
} }
static inline void ksft_print_cnts(void) static inline void ksft_print_cnts(void)
...@@ -137,13 +140,13 @@ static inline void ksft_print_cnts(void) ...@@ -137,13 +140,13 @@ static inline void ksft_print_cnts(void)
if (ksft_plan != ksft_test_num()) if (ksft_plan != ksft_test_num())
printf("# Planned tests != run tests (%u != %u)\n", printf("# Planned tests != run tests (%u != %u)\n",
ksft_plan, ksft_test_num()); ksft_plan, ksft_test_num());
printf("# Totals: pass:%d fail:%d xfail:%d xpass:%d skip:%d error:%d\n", printf("# Totals: pass:%u fail:%u xfail:%u xpass:%u skip:%u error:%u\n",
ksft_cnt.ksft_pass, ksft_cnt.ksft_fail, ksft_cnt.ksft_pass, ksft_cnt.ksft_fail,
ksft_cnt.ksft_xfail, ksft_cnt.ksft_xpass, ksft_cnt.ksft_xfail, ksft_cnt.ksft_xpass,
ksft_cnt.ksft_xskip, ksft_cnt.ksft_error); ksft_cnt.ksft_xskip, ksft_cnt.ksft_error);
} }
static inline void ksft_print_msg(const char *msg, ...) static inline __printf(1, 2) void ksft_print_msg(const char *msg, ...)
{ {
int saved_errno = errno; int saved_errno = errno;
va_list args; va_list args;
...@@ -155,7 +158,20 @@ static inline void ksft_print_msg(const char *msg, ...) ...@@ -155,7 +158,20 @@ static inline void ksft_print_msg(const char *msg, ...)
va_end(args); va_end(args);
} }
static inline void ksft_test_result_pass(const char *msg, ...) static inline void ksft_perror(const char *msg)
{
#ifndef NOLIBC
ksft_print_msg("%s: %s (%d)\n", msg, strerror(errno), errno);
#else
/*
* nolibc doesn't provide strerror() and it seems
* inappropriate to add one, just print the errno.
*/
ksft_print_msg("%s: %d)\n", msg, errno);
#endif
}
static inline __printf(1, 2) void ksft_test_result_pass(const char *msg, ...)
{ {
int saved_errno = errno; int saved_errno = errno;
va_list args; va_list args;
...@@ -163,13 +179,13 @@ static inline void ksft_test_result_pass(const char *msg, ...) ...@@ -163,13 +179,13 @@ static inline void ksft_test_result_pass(const char *msg, ...)
ksft_cnt.ksft_pass++; ksft_cnt.ksft_pass++;
va_start(args, msg); va_start(args, msg);
printf("ok %d ", ksft_test_num()); printf("ok %u ", ksft_test_num());
errno = saved_errno; errno = saved_errno;
vprintf(msg, args); vprintf(msg, args);
va_end(args); va_end(args);
} }
static inline void ksft_test_result_fail(const char *msg, ...) static inline __printf(1, 2) void ksft_test_result_fail(const char *msg, ...)
{ {
int saved_errno = errno; int saved_errno = errno;
va_list args; va_list args;
...@@ -177,7 +193,7 @@ static inline void ksft_test_result_fail(const char *msg, ...) ...@@ -177,7 +193,7 @@ static inline void ksft_test_result_fail(const char *msg, ...)
ksft_cnt.ksft_fail++; ksft_cnt.ksft_fail++;
va_start(args, msg); va_start(args, msg);
printf("not ok %d ", ksft_test_num()); printf("not ok %u ", ksft_test_num());
errno = saved_errno; errno = saved_errno;
vprintf(msg, args); vprintf(msg, args);
va_end(args); va_end(args);
...@@ -195,7 +211,7 @@ static inline void ksft_test_result_fail(const char *msg, ...) ...@@ -195,7 +211,7 @@ static inline void ksft_test_result_fail(const char *msg, ...)
ksft_test_result_fail(fmt, ##__VA_ARGS__);\ ksft_test_result_fail(fmt, ##__VA_ARGS__);\
} while (0) } while (0)
static inline void ksft_test_result_xfail(const char *msg, ...) static inline __printf(1, 2) void ksft_test_result_xfail(const char *msg, ...)
{ {
int saved_errno = errno; int saved_errno = errno;
va_list args; va_list args;
...@@ -203,13 +219,13 @@ static inline void ksft_test_result_xfail(const char *msg, ...) ...@@ -203,13 +219,13 @@ static inline void ksft_test_result_xfail(const char *msg, ...)
ksft_cnt.ksft_xfail++; ksft_cnt.ksft_xfail++;
va_start(args, msg); va_start(args, msg);
printf("ok %d # XFAIL ", ksft_test_num()); printf("ok %u # XFAIL ", ksft_test_num());
errno = saved_errno; errno = saved_errno;
vprintf(msg, args); vprintf(msg, args);
va_end(args); va_end(args);
} }
static inline void ksft_test_result_skip(const char *msg, ...) static inline __printf(1, 2) void ksft_test_result_skip(const char *msg, ...)
{ {
int saved_errno = errno; int saved_errno = errno;
va_list args; va_list args;
...@@ -217,14 +233,14 @@ static inline void ksft_test_result_skip(const char *msg, ...) ...@@ -217,14 +233,14 @@ static inline void ksft_test_result_skip(const char *msg, ...)
ksft_cnt.ksft_xskip++; ksft_cnt.ksft_xskip++;
va_start(args, msg); va_start(args, msg);
printf("ok %d # SKIP ", ksft_test_num()); printf("ok %u # SKIP ", ksft_test_num());
errno = saved_errno; errno = saved_errno;
vprintf(msg, args); vprintf(msg, args);
va_end(args); va_end(args);
} }
/* TODO: how does "error" differ from "fail" or "skip"? */ /* TODO: how does "error" differ from "fail" or "skip"? */
static inline void ksft_test_result_error(const char *msg, ...) static inline __printf(1, 2) void ksft_test_result_error(const char *msg, ...)
{ {
int saved_errno = errno; int saved_errno = errno;
va_list args; va_list args;
...@@ -232,7 +248,7 @@ static inline void ksft_test_result_error(const char *msg, ...) ...@@ -232,7 +248,7 @@ static inline void ksft_test_result_error(const char *msg, ...)
ksft_cnt.ksft_error++; ksft_cnt.ksft_error++;
va_start(args, msg); va_start(args, msg);
printf("not ok %d # error ", ksft_test_num()); printf("not ok %u # error ", ksft_test_num());
errno = saved_errno; errno = saved_errno;
vprintf(msg, args); vprintf(msg, args);
va_end(args); va_end(args);
...@@ -271,7 +287,7 @@ static inline int ksft_exit_fail(void) ...@@ -271,7 +287,7 @@ static inline int ksft_exit_fail(void)
ksft_cnt.ksft_xfail + \ ksft_cnt.ksft_xfail + \
ksft_cnt.ksft_xskip) ksft_cnt.ksft_xskip)
static inline int ksft_exit_fail_msg(const char *msg, ...) static inline __printf(1, 2) int ksft_exit_fail_msg(const char *msg, ...)
{ {
int saved_errno = errno; int saved_errno = errno;
va_list args; va_list args;
...@@ -298,7 +314,7 @@ static inline int ksft_exit_xpass(void) ...@@ -298,7 +314,7 @@ static inline int ksft_exit_xpass(void)
exit(KSFT_XPASS); exit(KSFT_XPASS);
} }
static inline int ksft_exit_skip(const char *msg, ...) static inline __printf(1, 2) int ksft_exit_skip(const char *msg, ...)
{ {
int saved_errno = errno; int saved_errno = errno;
va_list args; va_list args;
......
...@@ -33,7 +33,7 @@ static inline int _no_printf(const char *format, ...) { return 0; } ...@@ -33,7 +33,7 @@ static inline int _no_printf(const char *format, ...) { return 0; }
#define pr_info(...) _no_printf(__VA_ARGS__) #define pr_info(...) _no_printf(__VA_ARGS__)
#endif #endif
void print_skip(const char *fmt, ...) __attribute__((format(printf, 1, 2))); void __printf(1, 2) print_skip(const char *fmt, ...);
#define __TEST_REQUIRE(f, fmt, ...) \ #define __TEST_REQUIRE(f, fmt, ...) \
do { \ do { \
if (!(f)) \ if (!(f)) \
...@@ -46,9 +46,9 @@ ssize_t test_write(int fd, const void *buf, size_t count); ...@@ -46,9 +46,9 @@ ssize_t test_write(int fd, const void *buf, size_t count);
ssize_t test_read(int fd, void *buf, size_t count); ssize_t test_read(int fd, void *buf, size_t count);
int test_seq_read(const char *path, char **bufp, size_t *sizep); int test_seq_read(const char *path, char **bufp, size_t *sizep);
void test_assert(bool exp, const char *exp_str, void __printf(5, 6) test_assert(bool exp, const char *exp_str,
const char *file, unsigned int line, const char *fmt, ...) const char *file, unsigned int line,
__attribute__((format(printf, 5, 6))); const char *fmt, ...);
#define TEST_ASSERT(e, fmt, ...) \ #define TEST_ASSERT(e, fmt, ...) \
test_assert((e), #e, __FILE__, __LINE__, fmt, ##__VA_ARGS__) test_assert((e), #e, __FILE__, __LINE__, fmt, ##__VA_ARGS__)
......
...@@ -338,7 +338,7 @@ static long long remap_region(struct config c, unsigned int threshold_mb, ...@@ -338,7 +338,7 @@ static long long remap_region(struct config c, unsigned int threshold_mb,
char c = (char) rand(); char c = (char) rand();
if (((char *) dest_addr)[i] != c) { if (((char *) dest_addr)[i] != c) {
ksft_print_msg("Data after remap doesn't match at offset %d\n", ksft_print_msg("Data after remap doesn't match at offset %llu\n",
i); i);
ksft_print_msg("Expected: %#x\t Got: %#x\n", c & 0xff, ksft_print_msg("Expected: %#x\t Got: %#x\n", c & 0xff,
((char *) dest_addr)[i] & 0xff); ((char *) dest_addr)[i] & 0xff);
......
...@@ -34,7 +34,7 @@ extern int test_nr; ...@@ -34,7 +34,7 @@ extern int test_nr;
extern int iteration_nr; extern int iteration_nr;
#ifdef __GNUC__ #ifdef __GNUC__
__attribute__((format(printf, 1, 2))) __printf(1, 2)
#endif #endif
static inline void sigsafe_printf(const char *format, ...) static inline void sigsafe_printf(const char *format, ...)
{ {
......
...@@ -300,7 +300,7 @@ void test_openat2_flags(void) ...@@ -300,7 +300,7 @@ void test_openat2_flags(void)
ksft_print_msg("openat2 unexpectedly returned "); ksft_print_msg("openat2 unexpectedly returned ");
if (fdpath) if (fdpath)
ksft_print_msg("%d['%s'] with %X (!= %X)\n", ksft_print_msg("%d['%s'] with %X (!= %llX)\n",
fd, fdpath, fdflags, fd, fdpath, fdflags,
test->how.flags); test->how.flags);
else else
......
...@@ -62,7 +62,7 @@ static void error_report(struct error *err, const char *test_name) ...@@ -62,7 +62,7 @@ static void error_report(struct error *err, const char *test_name)
break; break;
case PIDFD_PASS: case PIDFD_PASS:
ksft_test_result_pass("%s test: Passed\n"); ksft_test_result_pass("%s test: Passed\n", test_name);
break; break;
default: default:
......
...@@ -381,13 +381,13 @@ static int test_pidfd_send_signal_syscall_support(void) ...@@ -381,13 +381,13 @@ static int test_pidfd_send_signal_syscall_support(void)
static void *test_pidfd_poll_exec_thread(void *priv) static void *test_pidfd_poll_exec_thread(void *priv)
{ {
ksft_print_msg("Child Thread: starting. pid %d tid %d ; and sleeping\n", ksft_print_msg("Child Thread: starting. pid %d tid %ld ; and sleeping\n",
getpid(), syscall(SYS_gettid)); getpid(), syscall(SYS_gettid));
ksft_print_msg("Child Thread: doing exec of sleep\n"); ksft_print_msg("Child Thread: doing exec of sleep\n");
execl("/bin/sleep", "sleep", str(CHILD_THREAD_MIN_WAIT), (char *)NULL); execl("/bin/sleep", "sleep", str(CHILD_THREAD_MIN_WAIT), (char *)NULL);
ksft_print_msg("Child Thread: DONE. pid %d tid %d\n", ksft_print_msg("Child Thread: DONE. pid %d tid %ld\n",
getpid(), syscall(SYS_gettid)); getpid(), syscall(SYS_gettid));
return NULL; return NULL;
} }
...@@ -427,7 +427,7 @@ static int child_poll_exec_test(void *args) ...@@ -427,7 +427,7 @@ static int child_poll_exec_test(void *args)
{ {
pthread_t t1; pthread_t t1;
ksft_print_msg("Child (pidfd): starting. pid %d tid %d\n", getpid(), ksft_print_msg("Child (pidfd): starting. pid %d tid %ld\n", getpid(),
syscall(SYS_gettid)); syscall(SYS_gettid));
pthread_create(&t1, NULL, test_pidfd_poll_exec_thread, NULL); pthread_create(&t1, NULL, test_pidfd_poll_exec_thread, NULL);
/* /*
...@@ -480,10 +480,10 @@ static void test_pidfd_poll_exec(int use_waitpid) ...@@ -480,10 +480,10 @@ static void test_pidfd_poll_exec(int use_waitpid)
static void *test_pidfd_poll_leader_exit_thread(void *priv) static void *test_pidfd_poll_leader_exit_thread(void *priv)
{ {
ksft_print_msg("Child Thread: starting. pid %d tid %d ; and sleeping\n", ksft_print_msg("Child Thread: starting. pid %d tid %ld ; and sleeping\n",
getpid(), syscall(SYS_gettid)); getpid(), syscall(SYS_gettid));
sleep(CHILD_THREAD_MIN_WAIT); sleep(CHILD_THREAD_MIN_WAIT);
ksft_print_msg("Child Thread: DONE. pid %d tid %d\n", getpid(), syscall(SYS_gettid)); ksft_print_msg("Child Thread: DONE. pid %d tid %ld\n", getpid(), syscall(SYS_gettid));
return NULL; return NULL;
} }
...@@ -492,7 +492,7 @@ static int child_poll_leader_exit_test(void *args) ...@@ -492,7 +492,7 @@ static int child_poll_leader_exit_test(void *args)
{ {
pthread_t t1, t2; pthread_t t1, t2;
ksft_print_msg("Child: starting. pid %d tid %d\n", getpid(), syscall(SYS_gettid)); ksft_print_msg("Child: starting. pid %d tid %ld\n", getpid(), syscall(SYS_gettid));
pthread_create(&t1, NULL, test_pidfd_poll_leader_exit_thread, NULL); pthread_create(&t1, NULL, test_pidfd_poll_leader_exit_thread, NULL);
pthread_create(&t2, NULL, test_pidfd_poll_leader_exit_thread, NULL); pthread_create(&t2, NULL, test_pidfd_poll_leader_exit_thread, NULL);
......
# SPDX-License-Identifier: GPL-2.0 # SPDX-License-Identifier: GPL-2.0
CFLAGS = -g -Wall -O2 -D_FORTIFY_SOURCE=2 CFLAGS = -g -Wall -O2 -D_FORTIFY_SOURCE=2 -D_GNU_SOURCE
CFLAGS += $(KHDR_INCLUDES) CFLAGS += $(KHDR_INCLUDES)
TEST_GEN_PROGS := resctrl_tests TEST_GEN_PROGS := resctrl_tests
......
...@@ -205,10 +205,11 @@ int measure_cache_vals(struct resctrl_val_param *param, int bm_pid) ...@@ -205,10 +205,11 @@ int measure_cache_vals(struct resctrl_val_param *param, int bm_pid)
* cache_val: execute benchmark and measure LLC occupancy resctrl * cache_val: execute benchmark and measure LLC occupancy resctrl
* and perf cache miss for the benchmark * and perf cache miss for the benchmark
* @param: parameters passed to cache_val() * @param: parameters passed to cache_val()
* @span: buffer size for the benchmark
* *
* Return: 0 on success. non-zero on failure. * Return: 0 on success. non-zero on failure.
*/ */
int cat_val(struct resctrl_val_param *param) int cat_val(struct resctrl_val_param *param, size_t span)
{ {
int memflush = 1, operation = 0, ret = 0; int memflush = 1, operation = 0, ret = 0;
char *resctrl_val = param->resctrl_val; char *resctrl_val = param->resctrl_val;
...@@ -245,7 +246,7 @@ int cat_val(struct resctrl_val_param *param) ...@@ -245,7 +246,7 @@ int cat_val(struct resctrl_val_param *param)
if (ret) if (ret)
break; break;
if (run_fill_buf(param->span, memflush, operation, true)) { if (run_fill_buf(span, memflush, operation, true)) {
fprintf(stderr, "Error-running fill buffer\n"); fprintf(stderr, "Error-running fill buffer\n");
ret = -1; ret = -1;
goto pe_close; goto pe_close;
...@@ -294,7 +295,7 @@ int show_cache_info(unsigned long sum_llc_val, int no_of_bits, ...@@ -294,7 +295,7 @@ int show_cache_info(unsigned long sum_llc_val, int no_of_bits,
ret = platform && abs((int)diff_percent) > max_diff_percent && ret = platform && abs((int)diff_percent) > max_diff_percent &&
(cmt ? (abs(avg_diff) > max_diff) : true); (cmt ? (abs(avg_diff) > max_diff) : true);
ksft_print_msg("%s Check cache miss rate within %d%%\n", ksft_print_msg("%s Check cache miss rate within %lu%%\n",
ret ? "Fail:" : "Pass:", max_diff_percent); ret ? "Fail:" : "Pass:", max_diff_percent);
ksft_print_msg("Percent diff=%d\n", abs((int)diff_percent)); ksft_print_msg("Percent diff=%d\n", abs((int)diff_percent));
......
...@@ -41,7 +41,7 @@ static int cat_setup(struct resctrl_val_param *p) ...@@ -41,7 +41,7 @@ static int cat_setup(struct resctrl_val_param *p)
return ret; return ret;
} }
static int check_results(struct resctrl_val_param *param) static int check_results(struct resctrl_val_param *param, size_t span)
{ {
char *token_array[8], temp[512]; char *token_array[8], temp[512];
unsigned long sum_llc_perf_miss = 0; unsigned long sum_llc_perf_miss = 0;
...@@ -76,7 +76,7 @@ static int check_results(struct resctrl_val_param *param) ...@@ -76,7 +76,7 @@ static int check_results(struct resctrl_val_param *param)
fclose(fp); fclose(fp);
no_of_bits = count_bits(param->mask); no_of_bits = count_bits(param->mask);
return show_cache_info(sum_llc_perf_miss, no_of_bits, param->span / 64, return show_cache_info(sum_llc_perf_miss, no_of_bits, span / 64,
MAX_DIFF, MAX_DIFF_PERCENT, runs - 1, MAX_DIFF, MAX_DIFF_PERCENT, runs - 1,
get_vendor() == ARCH_INTEL, false); get_vendor() == ARCH_INTEL, false);
} }
...@@ -96,6 +96,7 @@ int cat_perf_miss_val(int cpu_no, int n, char *cache_type) ...@@ -96,6 +96,7 @@ int cat_perf_miss_val(int cpu_no, int n, char *cache_type)
char cbm_mask[256]; char cbm_mask[256];
int count_of_bits; int count_of_bits;
char pipe_message; char pipe_message;
size_t span;
/* Get default cbm mask for L3/L2 cache */ /* Get default cbm mask for L3/L2 cache */
ret = get_cbm_mask(cache_type, cbm_mask); ret = get_cbm_mask(cache_type, cbm_mask);
...@@ -140,7 +141,7 @@ int cat_perf_miss_val(int cpu_no, int n, char *cache_type) ...@@ -140,7 +141,7 @@ int cat_perf_miss_val(int cpu_no, int n, char *cache_type)
/* Set param values for parent thread which will be allocated bitmask /* Set param values for parent thread which will be allocated bitmask
* with (max_bits - n) bits * with (max_bits - n) bits
*/ */
param.span = cache_size * (count_of_bits - n) / count_of_bits; span = cache_size * (count_of_bits - n) / count_of_bits;
strcpy(param.ctrlgrp, "c2"); strcpy(param.ctrlgrp, "c2");
strcpy(param.mongrp, "m2"); strcpy(param.mongrp, "m2");
strcpy(param.filename, RESULT_FILE_NAME2); strcpy(param.filename, RESULT_FILE_NAME2);
...@@ -162,23 +163,17 @@ int cat_perf_miss_val(int cpu_no, int n, char *cache_type) ...@@ -162,23 +163,17 @@ int cat_perf_miss_val(int cpu_no, int n, char *cache_type)
param.mask = l_mask_1; param.mask = l_mask_1;
strcpy(param.ctrlgrp, "c1"); strcpy(param.ctrlgrp, "c1");
strcpy(param.mongrp, "m1"); strcpy(param.mongrp, "m1");
param.span = cache_size * n / count_of_bits; span = cache_size * n / count_of_bits;
strcpy(param.filename, RESULT_FILE_NAME1); strcpy(param.filename, RESULT_FILE_NAME1);
param.num_of_runs = 0; param.num_of_runs = 0;
param.cpu_no = sibling_cpu_no; param.cpu_no = sibling_cpu_no;
} else {
ret = signal_handler_register();
if (ret) {
kill(bm_pid, SIGKILL);
goto out;
}
} }
remove(param.filename); remove(param.filename);
ret = cat_val(&param); ret = cat_val(&param, span);
if (ret == 0) if (ret == 0)
ret = check_results(&param); ret = check_results(&param, span);
if (bm_pid == 0) { if (bm_pid == 0) {
/* Tell parent that child is ready */ /* Tell parent that child is ready */
...@@ -208,10 +203,8 @@ int cat_perf_miss_val(int cpu_no, int n, char *cache_type) ...@@ -208,10 +203,8 @@ int cat_perf_miss_val(int cpu_no, int n, char *cache_type)
} }
close(pipefd[0]); close(pipefd[0]);
kill(bm_pid, SIGKILL); kill(bm_pid, SIGKILL);
signal_handler_unregister();
} }
out:
cat_test_cleanup(); cat_test_cleanup();
return ret; return ret;
......
...@@ -27,7 +27,7 @@ static int cmt_setup(struct resctrl_val_param *p) ...@@ -27,7 +27,7 @@ static int cmt_setup(struct resctrl_val_param *p)
return 0; return 0;
} }
static int check_results(struct resctrl_val_param *param, int no_of_bits) static int check_results(struct resctrl_val_param *param, size_t span, int no_of_bits)
{ {
char *token_array[8], temp[512]; char *token_array[8], temp[512];
unsigned long sum_llc_occu_resc = 0; unsigned long sum_llc_occu_resc = 0;
...@@ -58,7 +58,7 @@ static int check_results(struct resctrl_val_param *param, int no_of_bits) ...@@ -58,7 +58,7 @@ static int check_results(struct resctrl_val_param *param, int no_of_bits)
} }
fclose(fp); fclose(fp);
return show_cache_info(sum_llc_occu_resc, no_of_bits, param->span, return show_cache_info(sum_llc_occu_resc, no_of_bits, span,
MAX_DIFF, MAX_DIFF_PERCENT, runs - 1, MAX_DIFF, MAX_DIFF_PERCENT, runs - 1,
true, true); true, true);
} }
...@@ -68,16 +68,17 @@ void cmt_test_cleanup(void) ...@@ -68,16 +68,17 @@ void cmt_test_cleanup(void)
remove(RESULT_FILE_NAME); remove(RESULT_FILE_NAME);
} }
int cmt_resctrl_val(int cpu_no, int n, char **benchmark_cmd) int cmt_resctrl_val(int cpu_no, int n, const char * const *benchmark_cmd)
{ {
const char * const *cmd = benchmark_cmd;
const char *new_cmd[BENCHMARK_ARGS];
unsigned long cache_size = 0; unsigned long cache_size = 0;
unsigned long long_mask; unsigned long long_mask;
char *span_str = NULL;
char cbm_mask[256]; char cbm_mask[256];
int count_of_bits; int count_of_bits;
int ret; size_t span;
int ret, i;
if (!validate_resctrl_feature_request(CMT_STR))
return -1;
ret = get_cbm_mask("L3", cbm_mask); ret = get_cbm_mask("L3", cbm_mask);
if (ret) if (ret)
...@@ -105,24 +106,36 @@ int cmt_resctrl_val(int cpu_no, int n, char **benchmark_cmd) ...@@ -105,24 +106,36 @@ int cmt_resctrl_val(int cpu_no, int n, char **benchmark_cmd)
.cpu_no = cpu_no, .cpu_no = cpu_no,
.filename = RESULT_FILE_NAME, .filename = RESULT_FILE_NAME,
.mask = ~(long_mask << n) & long_mask, .mask = ~(long_mask << n) & long_mask,
.span = cache_size * n / count_of_bits,
.num_of_runs = 0, .num_of_runs = 0,
.setup = cmt_setup, .setup = cmt_setup,
}; };
if (strcmp(benchmark_cmd[0], "fill_buf") == 0) span = cache_size * n / count_of_bits;
sprintf(benchmark_cmd[1], "%zu", param.span);
if (strcmp(cmd[0], "fill_buf") == 0) {
/* Duplicate the command to be able to replace span in it */
for (i = 0; benchmark_cmd[i]; i++)
new_cmd[i] = benchmark_cmd[i];
new_cmd[i] = NULL;
ret = asprintf(&span_str, "%zu", span);
if (ret < 0)
return -1;
new_cmd[1] = span_str;
cmd = new_cmd;
}
remove(RESULT_FILE_NAME); remove(RESULT_FILE_NAME);
ret = resctrl_val(benchmark_cmd, &param); ret = resctrl_val(cmd, &param);
if (ret) if (ret)
goto out; goto out;
ret = check_results(&param, n); ret = check_results(&param, span, n);
out: out:
cmt_test_cleanup(); cmt_test_cleanup();
free(span_str);
return ret; return ret;
} }
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
#define RESULT_FILE_NAME "result_mba" #define RESULT_FILE_NAME "result_mba"
#define NUM_OF_RUNS 5 #define NUM_OF_RUNS 5
#define MAX_DIFF_PERCENT 5 #define MAX_DIFF_PERCENT 8
#define ALLOCATION_MAX 100 #define ALLOCATION_MAX 100
#define ALLOCATION_MIN 10 #define ALLOCATION_MIN 10
#define ALLOCATION_STEP 10 #define ALLOCATION_STEP 10
...@@ -141,7 +141,7 @@ void mba_test_cleanup(void) ...@@ -141,7 +141,7 @@ void mba_test_cleanup(void)
remove(RESULT_FILE_NAME); remove(RESULT_FILE_NAME);
} }
int mba_schemata_change(int cpu_no, char *bw_report, char **benchmark_cmd) int mba_schemata_change(int cpu_no, const char * const *benchmark_cmd)
{ {
struct resctrl_val_param param = { struct resctrl_val_param param = {
.resctrl_val = MBA_STR, .resctrl_val = MBA_STR,
...@@ -149,7 +149,7 @@ int mba_schemata_change(int cpu_no, char *bw_report, char **benchmark_cmd) ...@@ -149,7 +149,7 @@ int mba_schemata_change(int cpu_no, char *bw_report, char **benchmark_cmd)
.mongrp = "m1", .mongrp = "m1",
.cpu_no = cpu_no, .cpu_no = cpu_no,
.filename = RESULT_FILE_NAME, .filename = RESULT_FILE_NAME,
.bw_report = bw_report, .bw_report = "reads",
.setup = mba_setup .setup = mba_setup
}; };
int ret; int ret;
......
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
#include "resctrl.h" #include "resctrl.h"
#define RESULT_FILE_NAME "result_mbm" #define RESULT_FILE_NAME "result_mbm"
#define MAX_DIFF_PERCENT 5 #define MAX_DIFF_PERCENT 8
#define NUM_OF_RUNS 5 #define NUM_OF_RUNS 5
static int static int
...@@ -95,7 +95,7 @@ static int mbm_setup(struct resctrl_val_param *p) ...@@ -95,7 +95,7 @@ static int mbm_setup(struct resctrl_val_param *p)
return END_OF_TESTS; return END_OF_TESTS;
/* Set up shemata with 100% allocation on the first run. */ /* Set up shemata with 100% allocation on the first run. */
if (p->num_of_runs == 0) if (p->num_of_runs == 0 && validate_resctrl_feature_request("MB", NULL))
ret = write_schemata(p->ctrlgrp, "100", p->cpu_no, ret = write_schemata(p->ctrlgrp, "100", p->cpu_no,
p->resctrl_val); p->resctrl_val);
...@@ -109,16 +109,15 @@ void mbm_test_cleanup(void) ...@@ -109,16 +109,15 @@ void mbm_test_cleanup(void)
remove(RESULT_FILE_NAME); remove(RESULT_FILE_NAME);
} }
int mbm_bw_change(size_t span, int cpu_no, char *bw_report, char **benchmark_cmd) int mbm_bw_change(int cpu_no, const char * const *benchmark_cmd)
{ {
struct resctrl_val_param param = { struct resctrl_val_param param = {
.resctrl_val = MBM_STR, .resctrl_val = MBM_STR,
.ctrlgrp = "c1", .ctrlgrp = "c1",
.mongrp = "m1", .mongrp = "m1",
.span = span,
.cpu_no = cpu_no, .cpu_no = cpu_no,
.filename = RESULT_FILE_NAME, .filename = RESULT_FILE_NAME,
.bw_report = bw_report, .bw_report = "reads",
.setup = mbm_setup .setup = mbm_setup
}; };
int ret; int ret;
...@@ -129,7 +128,7 @@ int mbm_bw_change(size_t span, int cpu_no, char *bw_report, char **benchmark_cmd ...@@ -129,7 +128,7 @@ int mbm_bw_change(size_t span, int cpu_no, char *bw_report, char **benchmark_cmd
if (ret) if (ret)
goto out; goto out;
ret = check_results(span); ret = check_results(DEFAULT_SPAN);
out: out:
mbm_test_cleanup(); mbm_test_cleanup();
......
/* SPDX-License-Identifier: GPL-2.0 */ /* SPDX-License-Identifier: GPL-2.0 */
#define _GNU_SOURCE
#ifndef RESCTRL_H #ifndef RESCTRL_H
#define RESCTRL_H #define RESCTRL_H
#include <stdio.h> #include <stdio.h>
...@@ -28,16 +27,16 @@ ...@@ -28,16 +27,16 @@
#define RESCTRL_PATH "/sys/fs/resctrl" #define RESCTRL_PATH "/sys/fs/resctrl"
#define PHYS_ID_PATH "/sys/devices/system/cpu/cpu" #define PHYS_ID_PATH "/sys/devices/system/cpu/cpu"
#define INFO_PATH "/sys/fs/resctrl/info" #define INFO_PATH "/sys/fs/resctrl/info"
#define L3_PATH "/sys/fs/resctrl/info/L3"
#define MB_PATH "/sys/fs/resctrl/info/MB"
#define L3_MON_PATH "/sys/fs/resctrl/info/L3_MON"
#define L3_MON_FEATURES_PATH "/sys/fs/resctrl/info/L3_MON/mon_features"
#define ARCH_INTEL 1 #define ARCH_INTEL 1
#define ARCH_AMD 2 #define ARCH_AMD 2
#define END_OF_TESTS 1 #define END_OF_TESTS 1
#define BENCHMARK_ARGS 64
#define DEFAULT_SPAN (250 * MB)
#define PARENT_EXIT(err_msg) \ #define PARENT_EXIT(err_msg) \
do { \ do { \
perror(err_msg); \ perror(err_msg); \
...@@ -52,7 +51,6 @@ ...@@ -52,7 +51,6 @@
* @ctrlgrp: Name of the control monitor group (con_mon grp) * @ctrlgrp: Name of the control monitor group (con_mon grp)
* @mongrp: Name of the monitor group (mon grp) * @mongrp: Name of the monitor group (mon grp)
* @cpu_no: CPU number to which the benchmark would be binded * @cpu_no: CPU number to which the benchmark would be binded
* @span: Memory bytes accessed in each benchmark iteration
* @filename: Name of file to which the o/p should be written * @filename: Name of file to which the o/p should be written
* @bw_report: Bandwidth report type (reads vs writes) * @bw_report: Bandwidth report type (reads vs writes)
* @setup: Call back function to setup test environment * @setup: Call back function to setup test environment
...@@ -62,7 +60,6 @@ struct resctrl_val_param { ...@@ -62,7 +60,6 @@ struct resctrl_val_param {
char ctrlgrp[64]; char ctrlgrp[64];
char mongrp[64]; char mongrp[64];
int cpu_no; int cpu_no;
size_t span;
char filename[64]; char filename[64];
char *bw_report; char *bw_report;
unsigned long mask; unsigned long mask;
...@@ -86,10 +83,9 @@ int get_resource_id(int cpu_no, int *resource_id); ...@@ -86,10 +83,9 @@ int get_resource_id(int cpu_no, int *resource_id);
int mount_resctrlfs(void); int mount_resctrlfs(void);
int umount_resctrlfs(void); int umount_resctrlfs(void);
int validate_bw_report_request(char *bw_report); int validate_bw_report_request(char *bw_report);
bool validate_resctrl_feature_request(const char *resctrl_val); bool validate_resctrl_feature_request(const char *resource, const char *feature);
char *fgrep(FILE *inf, const char *str); char *fgrep(FILE *inf, const char *str);
int taskset_benchmark(pid_t bm_pid, int cpu_no); int taskset_benchmark(pid_t bm_pid, int cpu_no);
void run_benchmark(int signum, siginfo_t *info, void *ucontext);
int write_schemata(char *ctrlgrp, char *schemata, int cpu_no, int write_schemata(char *ctrlgrp, char *schemata, int cpu_no,
char *resctrl_val); char *resctrl_val);
int write_bm_pid_to_resctrl(pid_t bm_pid, char *ctrlgrp, char *mongrp, int write_bm_pid_to_resctrl(pid_t bm_pid, char *ctrlgrp, char *mongrp,
...@@ -97,21 +93,21 @@ int write_bm_pid_to_resctrl(pid_t bm_pid, char *ctrlgrp, char *mongrp, ...@@ -97,21 +93,21 @@ int write_bm_pid_to_resctrl(pid_t bm_pid, char *ctrlgrp, char *mongrp,
int perf_event_open(struct perf_event_attr *hw_event, pid_t pid, int cpu, int perf_event_open(struct perf_event_attr *hw_event, pid_t pid, int cpu,
int group_fd, unsigned long flags); int group_fd, unsigned long flags);
int run_fill_buf(size_t span, int memflush, int op, bool once); int run_fill_buf(size_t span, int memflush, int op, bool once);
int resctrl_val(char **benchmark_cmd, struct resctrl_val_param *param); int resctrl_val(const char * const *benchmark_cmd, struct resctrl_val_param *param);
int mbm_bw_change(size_t span, int cpu_no, char *bw_report, char **benchmark_cmd); int mbm_bw_change(int cpu_no, const char * const *benchmark_cmd);
void tests_cleanup(void); void tests_cleanup(void);
void mbm_test_cleanup(void); void mbm_test_cleanup(void);
int mba_schemata_change(int cpu_no, char *bw_report, char **benchmark_cmd); int mba_schemata_change(int cpu_no, const char * const *benchmark_cmd);
void mba_test_cleanup(void); void mba_test_cleanup(void);
int get_cbm_mask(char *cache_type, char *cbm_mask); int get_cbm_mask(char *cache_type, char *cbm_mask);
int get_cache_size(int cpu_no, char *cache_type, unsigned long *cache_size); int get_cache_size(int cpu_no, char *cache_type, unsigned long *cache_size);
void ctrlc_handler(int signum, siginfo_t *info, void *ptr); void ctrlc_handler(int signum, siginfo_t *info, void *ptr);
int signal_handler_register(void); int signal_handler_register(void);
void signal_handler_unregister(void); void signal_handler_unregister(void);
int cat_val(struct resctrl_val_param *param); int cat_val(struct resctrl_val_param *param, size_t span);
void cat_test_cleanup(void); void cat_test_cleanup(void);
int cat_perf_miss_val(int cpu_no, int no_of_bits, char *cache_type); int cat_perf_miss_val(int cpu_no, int no_of_bits, char *cache_type);
int cmt_resctrl_val(int cpu_no, int n, char **benchmark_cmd); int cmt_resctrl_val(int cpu_no, int n, const char * const *benchmark_cmd);
unsigned int count_bits(unsigned long n); unsigned int count_bits(unsigned long n);
void cmt_test_cleanup(void); void cmt_test_cleanup(void);
int get_core_sibling(int cpu_no); int get_core_sibling(int cpu_no);
......
...@@ -10,9 +10,6 @@ ...@@ -10,9 +10,6 @@
*/ */
#include "resctrl.h" #include "resctrl.h"
#define BENCHMARK_ARGS 64
#define BENCHMARK_ARG_SIZE 64
static int detect_vendor(void) static int detect_vendor(void)
{ {
FILE *inf = fopen("/proc/cpuinfo", "r"); FILE *inf = fopen("/proc/cpuinfo", "r");
...@@ -52,8 +49,8 @@ int get_vendor(void) ...@@ -52,8 +49,8 @@ int get_vendor(void)
static void cmd_help(void) static void cmd_help(void)
{ {
printf("usage: resctrl_tests [-h] [-b \"benchmark_cmd [options]\"] [-t test list] [-n no_of_bits]\n"); printf("usage: resctrl_tests [-h] [-t test list] [-n no_of_bits] [-b benchmark_cmd [option]...]\n");
printf("\t-b benchmark_cmd [options]: run specified benchmark for MBM, MBA and CMT\n"); printf("\t-b benchmark_cmd [option]...: run specified benchmark for MBM, MBA and CMT\n");
printf("\t default benchmark is builtin fill_buf\n"); printf("\t default benchmark is builtin fill_buf\n");
printf("\t-t test list: run tests specified in the test list, "); printf("\t-t test list: run tests specified in the test list, ");
printf("e.g. -t mbm,mba,cmt,cat\n"); printf("e.g. -t mbm,mba,cmt,cat\n");
...@@ -70,72 +67,98 @@ void tests_cleanup(void) ...@@ -70,72 +67,98 @@ void tests_cleanup(void)
cat_test_cleanup(); cat_test_cleanup();
} }
static void run_mbm_test(char **benchmark_cmd, size_t span, static int test_prepare(void)
int cpu_no, char *bw_report)
{ {
int res; int res;
ksft_print_msg("Starting MBM BW change ...\n"); res = signal_handler_register();
if (res) {
ksft_print_msg("Failed to register signal handler\n");
return res;
}
res = mount_resctrlfs(); res = mount_resctrlfs();
if (res) { if (res) {
ksft_exit_fail_msg("Failed to mount resctrl FS\n"); signal_handler_unregister();
ksft_print_msg("Failed to mount resctrl FS\n");
return res;
}
return 0;
}
static void test_cleanup(void)
{
umount_resctrlfs();
signal_handler_unregister();
}
static void run_mbm_test(const char * const *benchmark_cmd, int cpu_no)
{
int res;
ksft_print_msg("Starting MBM BW change ...\n");
if (test_prepare()) {
ksft_exit_fail_msg("Abnormal failure when preparing for the test\n");
return; return;
} }
if (!validate_resctrl_feature_request(MBM_STR) || (get_vendor() != ARCH_INTEL)) { if (!validate_resctrl_feature_request("L3_MON", "mbm_total_bytes") ||
!validate_resctrl_feature_request("L3_MON", "mbm_local_bytes") ||
(get_vendor() != ARCH_INTEL)) {
ksft_test_result_skip("Hardware does not support MBM or MBM is disabled\n"); ksft_test_result_skip("Hardware does not support MBM or MBM is disabled\n");
goto umount; goto cleanup;
} }
res = mbm_bw_change(span, cpu_no, bw_report, benchmark_cmd); res = mbm_bw_change(cpu_no, benchmark_cmd);
ksft_test_result(!res, "MBM: bw change\n"); ksft_test_result(!res, "MBM: bw change\n");
if ((get_vendor() == ARCH_INTEL) && res) if ((get_vendor() == ARCH_INTEL) && res)
ksft_print_msg("Intel MBM may be inaccurate when Sub-NUMA Clustering is enabled. Check BIOS configuration.\n"); ksft_print_msg("Intel MBM may be inaccurate when Sub-NUMA Clustering is enabled. Check BIOS configuration.\n");
umount: cleanup:
umount_resctrlfs(); test_cleanup();
} }
static void run_mba_test(char **benchmark_cmd, int cpu_no, char *bw_report) static void run_mba_test(const char * const *benchmark_cmd, int cpu_no)
{ {
int res; int res;
ksft_print_msg("Starting MBA Schemata change ...\n"); ksft_print_msg("Starting MBA Schemata change ...\n");
res = mount_resctrlfs(); if (test_prepare()) {
if (res) { ksft_exit_fail_msg("Abnormal failure when preparing for the test\n");
ksft_exit_fail_msg("Failed to mount resctrl FS\n");
return; return;
} }
if (!validate_resctrl_feature_request(MBA_STR) || (get_vendor() != ARCH_INTEL)) { if (!validate_resctrl_feature_request("MB", NULL) ||
!validate_resctrl_feature_request("L3_MON", "mbm_local_bytes") ||
(get_vendor() != ARCH_INTEL)) {
ksft_test_result_skip("Hardware does not support MBA or MBA is disabled\n"); ksft_test_result_skip("Hardware does not support MBA or MBA is disabled\n");
goto umount; goto cleanup;
} }
res = mba_schemata_change(cpu_no, bw_report, benchmark_cmd); res = mba_schemata_change(cpu_no, benchmark_cmd);
ksft_test_result(!res, "MBA: schemata change\n"); ksft_test_result(!res, "MBA: schemata change\n");
umount: cleanup:
umount_resctrlfs(); test_cleanup();
} }
static void run_cmt_test(char **benchmark_cmd, int cpu_no) static void run_cmt_test(const char * const *benchmark_cmd, int cpu_no)
{ {
int res; int res;
ksft_print_msg("Starting CMT test ...\n"); ksft_print_msg("Starting CMT test ...\n");
res = mount_resctrlfs(); if (test_prepare()) {
if (res) { ksft_exit_fail_msg("Abnormal failure when preparing for the test\n");
ksft_exit_fail_msg("Failed to mount resctrl FS\n");
return; return;
} }
if (!validate_resctrl_feature_request(CMT_STR)) { if (!validate_resctrl_feature_request("L3_MON", "llc_occupancy") ||
!validate_resctrl_feature_request("L3", NULL)) {
ksft_test_result_skip("Hardware does not support CMT or CMT is disabled\n"); ksft_test_result_skip("Hardware does not support CMT or CMT is disabled\n");
goto umount; goto cleanup;
} }
res = cmt_resctrl_val(cpu_no, 5, benchmark_cmd); res = cmt_resctrl_val(cpu_no, 5, benchmark_cmd);
...@@ -143,8 +166,8 @@ static void run_cmt_test(char **benchmark_cmd, int cpu_no) ...@@ -143,8 +166,8 @@ static void run_cmt_test(char **benchmark_cmd, int cpu_no)
if ((get_vendor() == ARCH_INTEL) && res) if ((get_vendor() == ARCH_INTEL) && res)
ksft_print_msg("Intel CMT may be inaccurate when Sub-NUMA Clustering is enabled. Check BIOS configuration.\n"); ksft_print_msg("Intel CMT may be inaccurate when Sub-NUMA Clustering is enabled. Check BIOS configuration.\n");
umount: cleanup:
umount_resctrlfs(); test_cleanup();
} }
static void run_cat_test(int cpu_no, int no_of_bits) static void run_cat_test(int cpu_no, int no_of_bits)
...@@ -153,48 +176,53 @@ static void run_cat_test(int cpu_no, int no_of_bits) ...@@ -153,48 +176,53 @@ static void run_cat_test(int cpu_no, int no_of_bits)
ksft_print_msg("Starting CAT test ...\n"); ksft_print_msg("Starting CAT test ...\n");
res = mount_resctrlfs(); if (test_prepare()) {
if (res) { ksft_exit_fail_msg("Abnormal failure when preparing for the test\n");
ksft_exit_fail_msg("Failed to mount resctrl FS\n");
return; return;
} }
if (!validate_resctrl_feature_request(CAT_STR)) { if (!validate_resctrl_feature_request("L3", NULL)) {
ksft_test_result_skip("Hardware does not support CAT or CAT is disabled\n"); ksft_test_result_skip("Hardware does not support CAT or CAT is disabled\n");
goto umount; goto cleanup;
} }
res = cat_perf_miss_val(cpu_no, no_of_bits, "L3"); res = cat_perf_miss_val(cpu_no, no_of_bits, "L3");
ksft_test_result(!res, "CAT: test\n"); ksft_test_result(!res, "CAT: test\n");
umount: cleanup:
umount_resctrlfs(); test_cleanup();
} }
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
bool has_ben = false, mbm_test = true, mba_test = true, cmt_test = true; bool mbm_test = true, mba_test = true, cmt_test = true;
char *benchmark_cmd[BENCHMARK_ARGS], bw_report[64], bm_type[64]; const char *benchmark_cmd[BENCHMARK_ARGS] = {};
char benchmark_cmd_area[BENCHMARK_ARGS][BENCHMARK_ARG_SIZE]; int c, cpu_no = 1, i, no_of_bits = 0;
int c, cpu_no = 1, argc_new = argc, i, no_of_bits = 0; char *span_str = NULL;
int ben_ind, ben_count, tests = 0;
size_t span = 250 * MB;
bool cat_test = true; bool cat_test = true;
int tests = 0;
int ret;
for (i = 0; i < argc; i++) { while ((c = getopt(argc, argv, "ht:b:n:p:")) != -1) {
if (strcmp(argv[i], "-b") == 0) {
ben_ind = i + 1;
ben_count = argc - ben_ind;
argc_new = ben_ind - 1;
has_ben = true;
break;
}
}
while ((c = getopt(argc_new, argv, "ht:b:n:p:")) != -1) {
char *token; char *token;
switch (c) { switch (c) {
case 'b':
/*
* First move optind back to the (first) optarg and
* then build the benchmark command using the
* remaining arguments.
*/
optind--;
if (argc - optind >= BENCHMARK_ARGS)
ksft_exit_fail_msg("Too long benchmark command");
/* Extract benchmark command from command line. */
for (i = 0; i < argc - optind; i++)
benchmark_cmd[i] = argv[i + optind];
benchmark_cmd[i] = NULL;
goto last_arg;
case 't': case 't':
token = strtok(optarg, ","); token = strtok(optarg, ",");
...@@ -243,6 +271,7 @@ int main(int argc, char **argv) ...@@ -243,6 +271,7 @@ int main(int argc, char **argv)
return -1; return -1;
} }
} }
last_arg:
ksft_print_header(); ksft_print_header();
...@@ -254,29 +283,6 @@ int main(int argc, char **argv) ...@@ -254,29 +283,6 @@ int main(int argc, char **argv)
if (geteuid() != 0) if (geteuid() != 0)
return ksft_exit_skip("Not running as root. Skipping...\n"); return ksft_exit_skip("Not running as root. Skipping...\n");
if (has_ben) {
/* Extract benchmark command from command line. */
for (i = ben_ind; i < argc; i++) {
benchmark_cmd[i - ben_ind] = benchmark_cmd_area[i];
sprintf(benchmark_cmd[i - ben_ind], "%s", argv[i]);
}
benchmark_cmd[ben_count] = NULL;
} else {
/* If no benchmark is given by "-b" argument, use fill_buf. */
for (i = 0; i < 5; i++)
benchmark_cmd[i] = benchmark_cmd_area[i];
strcpy(benchmark_cmd[0], "fill_buf");
sprintf(benchmark_cmd[1], "%zu", span);
strcpy(benchmark_cmd[2], "1");
strcpy(benchmark_cmd[3], "0");
strcpy(benchmark_cmd[4], "false");
benchmark_cmd[5] = NULL;
}
sprintf(bw_report, "reads");
sprintf(bm_type, "fill_buf");
if (!check_resctrlfs_support()) if (!check_resctrlfs_support())
return ksft_exit_skip("resctrl FS does not exist. Enable X86_CPU_RESCTRL config option.\n"); return ksft_exit_skip("resctrl FS does not exist. Enable X86_CPU_RESCTRL config option.\n");
...@@ -285,13 +291,26 @@ int main(int argc, char **argv) ...@@ -285,13 +291,26 @@ int main(int argc, char **argv)
filter_dmesg(); filter_dmesg();
if (!benchmark_cmd[0]) {
/* If no benchmark is given by "-b" argument, use fill_buf. */
benchmark_cmd[0] = "fill_buf";
ret = asprintf(&span_str, "%u", DEFAULT_SPAN);
if (ret < 0)
ksft_exit_fail_msg("Out of memory!\n");
benchmark_cmd[1] = span_str;
benchmark_cmd[2] = "1";
benchmark_cmd[3] = "0";
benchmark_cmd[4] = "false";
benchmark_cmd[5] = NULL;
}
ksft_set_plan(tests ? : 4); ksft_set_plan(tests ? : 4);
if (mbm_test) if (mbm_test)
run_mbm_test(benchmark_cmd, span, cpu_no, bw_report); run_mbm_test(benchmark_cmd, cpu_no);
if (mba_test) if (mba_test)
run_mba_test(benchmark_cmd, cpu_no, bw_report); run_mba_test(benchmark_cmd, cpu_no);
if (cmt_test) if (cmt_test)
run_cmt_test(benchmark_cmd, cpu_no); run_cmt_test(benchmark_cmd, cpu_no);
...@@ -299,5 +318,6 @@ int main(int argc, char **argv) ...@@ -299,5 +318,6 @@ int main(int argc, char **argv)
if (cat_test) if (cat_test)
run_cat_test(cpu_no, no_of_bits); run_cat_test(cpu_no, no_of_bits);
free(span_str);
ksft_finished(); ksft_finished();
} }
...@@ -468,6 +468,8 @@ pid_t bm_pid, ppid; ...@@ -468,6 +468,8 @@ pid_t bm_pid, ppid;
void ctrlc_handler(int signum, siginfo_t *info, void *ptr) void ctrlc_handler(int signum, siginfo_t *info, void *ptr)
{ {
/* Only kill child after bm_pid is set after fork() */
if (bm_pid)
kill(bm_pid, SIGKILL); kill(bm_pid, SIGKILL);
umount_resctrlfs(); umount_resctrlfs();
tests_cleanup(); tests_cleanup();
...@@ -482,9 +484,11 @@ void ctrlc_handler(int signum, siginfo_t *info, void *ptr) ...@@ -482,9 +484,11 @@ void ctrlc_handler(int signum, siginfo_t *info, void *ptr)
*/ */
int signal_handler_register(void) int signal_handler_register(void)
{ {
struct sigaction sigact; struct sigaction sigact = {};
int ret = 0; int ret = 0;
bm_pid = 0;
sigact.sa_sigaction = ctrlc_handler; sigact.sa_sigaction = ctrlc_handler;
sigemptyset(&sigact.sa_mask); sigemptyset(&sigact.sa_mask);
sigact.sa_flags = SA_SIGINFO; sigact.sa_flags = SA_SIGINFO;
...@@ -504,7 +508,7 @@ int signal_handler_register(void) ...@@ -504,7 +508,7 @@ int signal_handler_register(void)
*/ */
void signal_handler_unregister(void) void signal_handler_unregister(void)
{ {
struct sigaction sigact; struct sigaction sigact = {};
sigact.sa_handler = SIG_DFL; sigact.sa_handler = SIG_DFL;
sigemptyset(&sigact.sa_mask); sigemptyset(&sigact.sa_mask);
...@@ -621,6 +625,56 @@ measure_vals(struct resctrl_val_param *param, unsigned long *bw_resc_start) ...@@ -621,6 +625,56 @@ measure_vals(struct resctrl_val_param *param, unsigned long *bw_resc_start)
return 0; return 0;
} }
/*
* run_benchmark - Run a specified benchmark or fill_buf (default benchmark)
* in specified signal. Direct benchmark stdio to /dev/null.
* @signum: signal number
* @info: signal info
* @ucontext: user context in signal handling
*/
static void run_benchmark(int signum, siginfo_t *info, void *ucontext)
{
int operation, ret, memflush;
char **benchmark_cmd;
size_t span;
bool once;
FILE *fp;
benchmark_cmd = info->si_ptr;
/*
* Direct stdio of child to /dev/null, so that only parent writes to
* stdio (console)
*/
fp = freopen("/dev/null", "w", stdout);
if (!fp)
PARENT_EXIT("Unable to direct benchmark status to /dev/null");
if (strcmp(benchmark_cmd[0], "fill_buf") == 0) {
/* Execute default fill_buf benchmark */
span = strtoul(benchmark_cmd[1], NULL, 10);
memflush = atoi(benchmark_cmd[2]);
operation = atoi(benchmark_cmd[3]);
if (!strcmp(benchmark_cmd[4], "true"))
once = true;
else if (!strcmp(benchmark_cmd[4], "false"))
once = false;
else
PARENT_EXIT("Invalid once parameter");
if (run_fill_buf(span, memflush, operation, once))
fprintf(stderr, "Error in running fill buffer\n");
} else {
/* Execute specified benchmark */
ret = execvp(benchmark_cmd[0], benchmark_cmd);
if (ret)
perror("wrong\n");
}
fclose(stdout);
PARENT_EXIT("Unable to run specified benchmark");
}
/* /*
* resctrl_val: execute benchmark and measure memory bandwidth on * resctrl_val: execute benchmark and measure memory bandwidth on
* the benchmark * the benchmark
...@@ -629,7 +683,7 @@ measure_vals(struct resctrl_val_param *param, unsigned long *bw_resc_start) ...@@ -629,7 +683,7 @@ measure_vals(struct resctrl_val_param *param, unsigned long *bw_resc_start)
* *
* Return: 0 on success. non-zero on failure. * Return: 0 on success. non-zero on failure.
*/ */
int resctrl_val(char **benchmark_cmd, struct resctrl_val_param *param) int resctrl_val(const char * const *benchmark_cmd, struct resctrl_val_param *param)
{ {
char *resctrl_val = param->resctrl_val; char *resctrl_val = param->resctrl_val;
unsigned long bw_resc_start = 0; unsigned long bw_resc_start = 0;
...@@ -706,28 +760,30 @@ int resctrl_val(char **benchmark_cmd, struct resctrl_val_param *param) ...@@ -706,28 +760,30 @@ int resctrl_val(char **benchmark_cmd, struct resctrl_val_param *param)
ksft_print_msg("Benchmark PID: %d\n", bm_pid); ksft_print_msg("Benchmark PID: %d\n", bm_pid);
ret = signal_handler_register(); /*
if (ret) * The cast removes constness but nothing mutates benchmark_cmd within
goto out; * the context of this process. At the receiving process, it becomes
* argv, which is mutable, on exec() but that's after fork() so it
value.sival_ptr = benchmark_cmd; * doesn't matter for the process running the tests.
*/
value.sival_ptr = (void *)benchmark_cmd;
/* Taskset benchmark to specified cpu */ /* Taskset benchmark to specified cpu */
ret = taskset_benchmark(bm_pid, param->cpu_no); ret = taskset_benchmark(bm_pid, param->cpu_no);
if (ret) if (ret)
goto unregister; goto out;
/* Write benchmark to specified control&monitoring grp in resctrl FS */ /* Write benchmark to specified control&monitoring grp in resctrl FS */
ret = write_bm_pid_to_resctrl(bm_pid, param->ctrlgrp, param->mongrp, ret = write_bm_pid_to_resctrl(bm_pid, param->ctrlgrp, param->mongrp,
resctrl_val); resctrl_val);
if (ret) if (ret)
goto unregister; goto out;
if (!strncmp(resctrl_val, MBM_STR, sizeof(MBM_STR)) || if (!strncmp(resctrl_val, MBM_STR, sizeof(MBM_STR)) ||
!strncmp(resctrl_val, MBA_STR, sizeof(MBA_STR))) { !strncmp(resctrl_val, MBA_STR, sizeof(MBA_STR))) {
ret = initialize_mem_bw_imc(); ret = initialize_mem_bw_imc();
if (ret) if (ret)
goto unregister; goto out;
initialize_mem_bw_resctrl(param->ctrlgrp, param->mongrp, initialize_mem_bw_resctrl(param->ctrlgrp, param->mongrp,
param->cpu_no, resctrl_val); param->cpu_no, resctrl_val);
...@@ -742,7 +798,7 @@ int resctrl_val(char **benchmark_cmd, struct resctrl_val_param *param) ...@@ -742,7 +798,7 @@ int resctrl_val(char **benchmark_cmd, struct resctrl_val_param *param)
sizeof(pipe_message)) { sizeof(pipe_message)) {
perror("# failed reading message from child process"); perror("# failed reading message from child process");
close(pipefd[0]); close(pipefd[0]);
goto unregister; goto out;
} }
} }
close(pipefd[0]); close(pipefd[0]);
...@@ -751,7 +807,7 @@ int resctrl_val(char **benchmark_cmd, struct resctrl_val_param *param) ...@@ -751,7 +807,7 @@ int resctrl_val(char **benchmark_cmd, struct resctrl_val_param *param)
if (sigqueue(bm_pid, SIGUSR1, value) == -1) { if (sigqueue(bm_pid, SIGUSR1, value) == -1) {
perror("# sigqueue SIGUSR1 to child"); perror("# sigqueue SIGUSR1 to child");
ret = errno; ret = errno;
goto unregister; goto out;
} }
/* Give benchmark enough time to fully run */ /* Give benchmark enough time to fully run */
...@@ -780,8 +836,6 @@ int resctrl_val(char **benchmark_cmd, struct resctrl_val_param *param) ...@@ -780,8 +836,6 @@ int resctrl_val(char **benchmark_cmd, struct resctrl_val_param *param)
} }
} }
unregister:
signal_handler_unregister();
out: out:
kill(bm_pid, SIGKILL); kill(bm_pid, SIGKILL);
......
...@@ -8,6 +8,9 @@ ...@@ -8,6 +8,9 @@
* Sai Praneeth Prakhya <sai.praneeth.prakhya@intel.com>, * Sai Praneeth Prakhya <sai.praneeth.prakhya@intel.com>,
* Fenghua Yu <fenghua.yu@intel.com> * Fenghua Yu <fenghua.yu@intel.com>
*/ */
#include <fcntl.h>
#include <limits.h>
#include "resctrl.h" #include "resctrl.h"
static int find_resctrl_mount(char *buffer) static int find_resctrl_mount(char *buffer)
...@@ -291,58 +294,6 @@ int taskset_benchmark(pid_t bm_pid, int cpu_no) ...@@ -291,58 +294,6 @@ int taskset_benchmark(pid_t bm_pid, int cpu_no)
return 0; return 0;
} }
/*
* run_benchmark - Run a specified benchmark or fill_buf (default benchmark)
* in specified signal. Direct benchmark stdio to /dev/null.
* @signum: signal number
* @info: signal info
* @ucontext: user context in signal handling
*
* Return: void
*/
void run_benchmark(int signum, siginfo_t *info, void *ucontext)
{
int operation, ret, memflush;
char **benchmark_cmd;
size_t span;
bool once;
FILE *fp;
benchmark_cmd = info->si_ptr;
/*
* Direct stdio of child to /dev/null, so that only parent writes to
* stdio (console)
*/
fp = freopen("/dev/null", "w", stdout);
if (!fp)
PARENT_EXIT("Unable to direct benchmark status to /dev/null");
if (strcmp(benchmark_cmd[0], "fill_buf") == 0) {
/* Execute default fill_buf benchmark */
span = strtoul(benchmark_cmd[1], NULL, 10);
memflush = atoi(benchmark_cmd[2]);
operation = atoi(benchmark_cmd[3]);
if (!strcmp(benchmark_cmd[4], "true"))
once = true;
else if (!strcmp(benchmark_cmd[4], "false"))
once = false;
else
PARENT_EXIT("Invalid once parameter");
if (run_fill_buf(span, memflush, operation, once))
fprintf(stderr, "Error in running fill buffer\n");
} else {
/* Execute specified benchmark */
ret = execvp(benchmark_cmd[0], benchmark_cmd);
if (ret)
perror("wrong\n");
}
fclose(stdout);
PARENT_EXIT("Unable to run specified benchmark");
}
/* /*
* create_grp - Create a group only if one doesn't exist * create_grp - Create a group only if one doesn't exist
* @grp_name: Name of the group * @grp_name: Name of the group
...@@ -488,9 +439,8 @@ int write_bm_pid_to_resctrl(pid_t bm_pid, char *ctrlgrp, char *mongrp, ...@@ -488,9 +439,8 @@ int write_bm_pid_to_resctrl(pid_t bm_pid, char *ctrlgrp, char *mongrp,
*/ */
int write_schemata(char *ctrlgrp, char *schemata, int cpu_no, char *resctrl_val) int write_schemata(char *ctrlgrp, char *schemata, int cpu_no, char *resctrl_val)
{ {
char controlgroup[1024], schema[1024], reason[64]; char controlgroup[1024], reason[128], schema[1024] = {};
int resource_id, ret = 0; int resource_id, fd, schema_len = -1, ret = 0;
FILE *fp;
if (strncmp(resctrl_val, MBA_STR, sizeof(MBA_STR)) && if (strncmp(resctrl_val, MBA_STR, sizeof(MBA_STR)) &&
strncmp(resctrl_val, MBM_STR, sizeof(MBM_STR)) && strncmp(resctrl_val, MBM_STR, sizeof(MBM_STR)) &&
...@@ -518,28 +468,39 @@ int write_schemata(char *ctrlgrp, char *schemata, int cpu_no, char *resctrl_val) ...@@ -518,28 +468,39 @@ int write_schemata(char *ctrlgrp, char *schemata, int cpu_no, char *resctrl_val)
if (!strncmp(resctrl_val, CAT_STR, sizeof(CAT_STR)) || if (!strncmp(resctrl_val, CAT_STR, sizeof(CAT_STR)) ||
!strncmp(resctrl_val, CMT_STR, sizeof(CMT_STR))) !strncmp(resctrl_val, CMT_STR, sizeof(CMT_STR)))
sprintf(schema, "%s%d%c%s", "L3:", resource_id, '=', schemata); schema_len = snprintf(schema, sizeof(schema), "%s%d%c%s\n",
"L3:", resource_id, '=', schemata);
if (!strncmp(resctrl_val, MBA_STR, sizeof(MBA_STR)) || if (!strncmp(resctrl_val, MBA_STR, sizeof(MBA_STR)) ||
!strncmp(resctrl_val, MBM_STR, sizeof(MBM_STR))) !strncmp(resctrl_val, MBM_STR, sizeof(MBM_STR)))
sprintf(schema, "%s%d%c%s", "MB:", resource_id, '=', schemata); schema_len = snprintf(schema, sizeof(schema), "%s%d%c%s\n",
"MB:", resource_id, '=', schemata);
fp = fopen(controlgroup, "w"); if (schema_len < 0 || schema_len >= sizeof(schema)) {
if (!fp) { snprintf(reason, sizeof(reason),
sprintf(reason, "Failed to open control group"); "snprintf() failed with return value : %d", schema_len);
ret = -1; ret = -1;
goto out; goto out;
} }
if (fprintf(fp, "%s\n", schema) < 0) { fd = open(controlgroup, O_WRONLY);
sprintf(reason, "Failed to write schemata in control group"); if (fd < 0) {
fclose(fp); snprintf(reason, sizeof(reason),
"open() failed : %s", strerror(errno));
ret = -1; ret = -1;
goto out; goto err_schema_not_empty;
} }
fclose(fp); if (write(fd, schema, schema_len) < 0) {
snprintf(reason, sizeof(reason),
"write() failed : %s", strerror(errno));
close(fd);
ret = -1;
goto err_schema_not_empty;
}
close(fd);
err_schema_not_empty:
schema[schema_len - 1] = 0;
out: out:
ksft_print_msg("Write schema \"%s\" to resctrl FS%s%s\n", ksft_print_msg("Write schema \"%s\" to resctrl FS%s%s\n",
schema, ret ? " # " : "", schema, ret ? " # " : "",
...@@ -604,63 +565,46 @@ char *fgrep(FILE *inf, const char *str) ...@@ -604,63 +565,46 @@ char *fgrep(FILE *inf, const char *str)
/* /*
* validate_resctrl_feature_request - Check if requested feature is valid. * validate_resctrl_feature_request - Check if requested feature is valid.
* @resctrl_val: Requested feature * @resource: Required resource (e.g., MB, L3, L2, L3_MON, etc.)
* @feature: Required monitor feature (in mon_features file). Can only be
* set for L3_MON. Must be NULL for all other resources.
* *
* Return: True if the feature is supported, else false. False is also * Return: True if the resource/feature is supported, else false. False is
* returned if resctrl FS is not mounted. * also returned if resctrl FS is not mounted.
*/ */
bool validate_resctrl_feature_request(const char *resctrl_val) bool validate_resctrl_feature_request(const char *resource, const char *feature)
{ {
char res_path[PATH_MAX];
struct stat statbuf; struct stat statbuf;
bool found = false;
char *res; char *res;
FILE *inf; FILE *inf;
int ret; int ret;
if (!resctrl_val) if (!resource)
return false; return false;
ret = find_resctrl_mount(NULL); ret = find_resctrl_mount(NULL);
if (ret) if (ret)
return false; return false;
if (!strncmp(resctrl_val, CAT_STR, sizeof(CAT_STR))) { snprintf(res_path, sizeof(res_path), "%s/%s", INFO_PATH, resource);
if (!stat(L3_PATH, &statbuf))
return true; if (stat(res_path, &statbuf))
} else if (!strncmp(resctrl_val, MBA_STR, sizeof(MBA_STR))) { return false;
if (!stat(MB_PATH, &statbuf))
if (!feature)
return true; return true;
} else if (!strncmp(resctrl_val, MBM_STR, sizeof(MBM_STR)) ||
!strncmp(resctrl_val, CMT_STR, sizeof(CMT_STR))) { snprintf(res_path, sizeof(res_path), "%s/%s/mon_features", INFO_PATH, resource);
if (!stat(L3_MON_PATH, &statbuf)) { inf = fopen(res_path, "r");
inf = fopen(L3_MON_FEATURES_PATH, "r");
if (!inf) if (!inf)
return false; return false;
if (!strncmp(resctrl_val, CMT_STR, sizeof(CMT_STR))) { res = fgrep(inf, feature);
res = fgrep(inf, "llc_occupancy");
if (res) {
found = true;
free(res); free(res);
}
}
if (!strncmp(resctrl_val, MBM_STR, sizeof(MBM_STR))) {
res = fgrep(inf, "mbm_total_bytes");
if (res) {
free(res);
res = fgrep(inf, "mbm_local_bytes");
if (res) {
found = true;
free(res);
}
}
}
fclose(inf); fclose(inf);
}
}
return found; return !!res;
} }
int filter_dmesg(void) int filter_dmesg(void)
......
...@@ -1231,7 +1231,7 @@ void *test_membarrier_worker_thread(void *arg) ...@@ -1231,7 +1231,7 @@ void *test_membarrier_worker_thread(void *arg)
} }
/* Wait for initialization. */ /* Wait for initialization. */
while (!atomic_load(&args->percpu_list_ptr)) {} while (!__atomic_load_n(&args->percpu_list_ptr, __ATOMIC_ACQUIRE)) {}
for (i = 0; i < iters; ++i) { for (i = 0; i < iters; ++i) {
int ret; int ret;
...@@ -1299,22 +1299,22 @@ void *test_membarrier_manager_thread(void *arg) ...@@ -1299,22 +1299,22 @@ void *test_membarrier_manager_thread(void *arg)
test_membarrier_init_percpu_list(&list_a); test_membarrier_init_percpu_list(&list_a);
test_membarrier_init_percpu_list(&list_b); test_membarrier_init_percpu_list(&list_b);
atomic_store(&args->percpu_list_ptr, (intptr_t)&list_a); __atomic_store_n(&args->percpu_list_ptr, (intptr_t)&list_a, __ATOMIC_RELEASE);
while (!atomic_load(&args->stop)) { while (!__atomic_load_n(&args->stop, __ATOMIC_ACQUIRE)) {
/* list_a is "active". */ /* list_a is "active". */
cpu_a = rand() % CPU_SETSIZE; cpu_a = rand() % CPU_SETSIZE;
/* /*
* As list_b is "inactive", we should never see changes * As list_b is "inactive", we should never see changes
* to list_b. * to list_b.
*/ */
if (expect_b != atomic_load(&list_b.c[cpu_b].head->data)) { if (expect_b != __atomic_load_n(&list_b.c[cpu_b].head->data, __ATOMIC_ACQUIRE)) {
fprintf(stderr, "Membarrier test failed\n"); fprintf(stderr, "Membarrier test failed\n");
abort(); abort();
} }
/* Make list_b "active". */ /* Make list_b "active". */
atomic_store(&args->percpu_list_ptr, (intptr_t)&list_b); __atomic_store_n(&args->percpu_list_ptr, (intptr_t)&list_b, __ATOMIC_RELEASE);
if (rseq_membarrier_expedited(cpu_a) && if (rseq_membarrier_expedited(cpu_a) &&
errno != ENXIO /* missing CPU */) { errno != ENXIO /* missing CPU */) {
perror("sys_membarrier"); perror("sys_membarrier");
...@@ -1324,27 +1324,27 @@ void *test_membarrier_manager_thread(void *arg) ...@@ -1324,27 +1324,27 @@ void *test_membarrier_manager_thread(void *arg)
* Cpu A should now only modify list_b, so the values * Cpu A should now only modify list_b, so the values
* in list_a should be stable. * in list_a should be stable.
*/ */
expect_a = atomic_load(&list_a.c[cpu_a].head->data); expect_a = __atomic_load_n(&list_a.c[cpu_a].head->data, __ATOMIC_ACQUIRE);
cpu_b = rand() % CPU_SETSIZE; cpu_b = rand() % CPU_SETSIZE;
/* /*
* As list_a is "inactive", we should never see changes * As list_a is "inactive", we should never see changes
* to list_a. * to list_a.
*/ */
if (expect_a != atomic_load(&list_a.c[cpu_a].head->data)) { if (expect_a != __atomic_load_n(&list_a.c[cpu_a].head->data, __ATOMIC_ACQUIRE)) {
fprintf(stderr, "Membarrier test failed\n"); fprintf(stderr, "Membarrier test failed\n");
abort(); abort();
} }
/* Make list_a "active". */ /* Make list_a "active". */
atomic_store(&args->percpu_list_ptr, (intptr_t)&list_a); __atomic_store_n(&args->percpu_list_ptr, (intptr_t)&list_a, __ATOMIC_RELEASE);
if (rseq_membarrier_expedited(cpu_b) && if (rseq_membarrier_expedited(cpu_b) &&
errno != ENXIO /* missing CPU*/) { errno != ENXIO /* missing CPU*/) {
perror("sys_membarrier"); perror("sys_membarrier");
abort(); abort();
} }
/* Remember a value from list_b. */ /* Remember a value from list_b. */
expect_b = atomic_load(&list_b.c[cpu_b].head->data); expect_b = __atomic_load_n(&list_b.c[cpu_b].head->data, __ATOMIC_ACQUIRE);
} }
test_membarrier_free_percpu_list(&list_a); test_membarrier_free_percpu_list(&list_a);
...@@ -1401,7 +1401,7 @@ void test_membarrier(void) ...@@ -1401,7 +1401,7 @@ void test_membarrier(void)
} }
} }
atomic_store(&thread_args.stop, 1); __atomic_store_n(&thread_args.stop, 1, __ATOMIC_RELEASE);
ret = pthread_join(manager_thread, NULL); ret = pthread_join(manager_thread, NULL);
if (ret) { if (ret) {
errno = ret; errno = ret;
......
...@@ -111,7 +111,7 @@ int main(void) ...@@ -111,7 +111,7 @@ int main(void)
/* Make sure more than the required minimum. */ /* Make sure more than the required minimum. */
stack_size = getauxval(AT_MINSIGSTKSZ) + SIGSTKSZ; stack_size = getauxval(AT_MINSIGSTKSZ) + SIGSTKSZ;
ksft_print_msg("[NOTE]\tthe stack size is %lu\n", stack_size); ksft_print_msg("[NOTE]\tthe stack size is %u\n", stack_size);
ksft_print_header(); ksft_print_header();
ksft_set_plan(3); ksft_set_plan(3);
......
...@@ -6,18 +6,18 @@ ...@@ -6,18 +6,18 @@
ksft_skip=4 ksft_skip=4
if ! /sbin/modprobe -q -n test_static_key_base; then if ! /sbin/modprobe -q -n test_static_key_base; then
echo "static_key: module test_static_key_base is not found [SKIP]" echo "static_keys: module test_static_key_base is not found [SKIP]"
exit $ksft_skip exit $ksft_skip
fi fi
if ! /sbin/modprobe -q -n test_static_keys; then if ! /sbin/modprobe -q -n test_static_keys; then
echo "static_key: module test_static_keys is not found [SKIP]" echo "static_keys: module test_static_keys is not found [SKIP]"
exit $ksft_skip exit $ksft_skip
fi fi
if /sbin/modprobe -q test_static_key_base; then if /sbin/modprobe -q test_static_key_base; then
if /sbin/modprobe -q test_static_keys; then if /sbin/modprobe -q test_static_keys; then
echo "static_key: ok" echo "static_keys: ok"
/sbin/modprobe -q -r test_static_keys /sbin/modprobe -q -r test_static_keys
/sbin/modprobe -q -r test_static_key_base /sbin/modprobe -q -r test_static_key_base
else else
...@@ -25,6 +25,6 @@ if /sbin/modprobe -q test_static_key_base; then ...@@ -25,6 +25,6 @@ if /sbin/modprobe -q test_static_key_base; then
/sbin/modprobe -q -r test_static_key_base /sbin/modprobe -q -r test_static_key_base
fi fi
else else
echo "static_key: [FAIL]" echo "static_keys: [FAIL]"
exit 1 exit 1
fi fi
...@@ -118,7 +118,7 @@ int nanosleep_lat_test(int clockid, long long ns) ...@@ -118,7 +118,7 @@ int nanosleep_lat_test(int clockid, long long ns)
clock_gettime(clockid, &end); clock_gettime(clockid, &end);
if (((timespec_sub(start, end)/count)-ns) > UNRESONABLE_LATENCY) { if (((timespec_sub(start, end)/count)-ns) > UNRESONABLE_LATENCY) {
printf("Large rel latency: %lld ns :", (timespec_sub(start, end)/count)-ns); ksft_print_msg("Large rel latency: %lld ns :", (timespec_sub(start, end)/count)-ns);
return -1; return -1;
} }
...@@ -132,20 +132,23 @@ int nanosleep_lat_test(int clockid, long long ns) ...@@ -132,20 +132,23 @@ int nanosleep_lat_test(int clockid, long long ns)
} }
if (latency/count > UNRESONABLE_LATENCY) { if (latency/count > UNRESONABLE_LATENCY) {
printf("Large abs latency: %lld ns :", latency/count); ksft_print_msg("Large abs latency: %lld ns :", latency/count);
return -1; return -1;
} }
return 0; return 0;
} }
#define SKIPPED_CLOCK_COUNT 3
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
long long length; long long length;
int clockid, ret; int clockid, ret;
ksft_print_header();
ksft_set_plan(NR_CLOCKIDS - CLOCK_REALTIME - SKIPPED_CLOCK_COUNT);
for (clockid = CLOCK_REALTIME; clockid < NR_CLOCKIDS; clockid++) { for (clockid = CLOCK_REALTIME; clockid < NR_CLOCKIDS; clockid++) {
/* Skip cputime clockids since nanosleep won't increment cputime */ /* Skip cputime clockids since nanosleep won't increment cputime */
...@@ -154,9 +157,6 @@ int main(int argc, char **argv) ...@@ -154,9 +157,6 @@ int main(int argc, char **argv)
clockid == CLOCK_HWSPECIFIC) clockid == CLOCK_HWSPECIFIC)
continue; continue;
printf("nsleep latency %-26s ", clockstring(clockid));
fflush(stdout);
length = 10; length = 10;
while (length <= (NSEC_PER_SEC * 10)) { while (length <= (NSEC_PER_SEC * 10)) {
ret = nanosleep_lat_test(clockid, length); ret = nanosleep_lat_test(clockid, length);
...@@ -167,14 +167,12 @@ int main(int argc, char **argv) ...@@ -167,14 +167,12 @@ int main(int argc, char **argv)
} }
if (ret == UNSUPPORTED) { if (ret == UNSUPPORTED) {
printf("[UNSUPPORTED]\n"); ksft_test_result_skip("%s\n", clockstring(clockid));
continue; } else {
} ksft_test_result(ret >= 0, "%s\n",
if (ret < 0) { clockstring(clockid));
printf("[FAILED]\n");
return ksft_exit_fail();
} }
printf("[OK]\n");
} }
return ksft_exit_pass();
ksft_finished();
} }
...@@ -76,22 +76,21 @@ static int check_diff(struct timeval start, struct timeval end) ...@@ -76,22 +76,21 @@ static int check_diff(struct timeval start, struct timeval end)
static int check_itimer(int which) static int check_itimer(int which)
{ {
const char *name;
int err; int err;
struct timeval start, end; struct timeval start, end;
struct itimerval val = { struct itimerval val = {
.it_value.tv_sec = DELAY, .it_value.tv_sec = DELAY,
}; };
printf("Check itimer ");
if (which == ITIMER_VIRTUAL) if (which == ITIMER_VIRTUAL)
printf("virtual... "); name = "ITIMER_VIRTUAL";
else if (which == ITIMER_PROF) else if (which == ITIMER_PROF)
printf("prof... "); name = "ITIMER_PROF";
else if (which == ITIMER_REAL) else if (which == ITIMER_REAL)
printf("real... "); name = "ITIMER_REAL";
else
fflush(stdout); return -1;
done = 0; done = 0;
...@@ -104,13 +103,13 @@ static int check_itimer(int which) ...@@ -104,13 +103,13 @@ static int check_itimer(int which)
err = gettimeofday(&start, NULL); err = gettimeofday(&start, NULL);
if (err < 0) { if (err < 0) {
perror("Can't call gettimeofday()\n"); ksft_perror("Can't call gettimeofday()");
return -1; return -1;
} }
err = setitimer(which, &val, NULL); err = setitimer(which, &val, NULL);
if (err < 0) { if (err < 0) {
perror("Can't set timer\n"); ksft_perror("Can't set timer");
return -1; return -1;
} }
...@@ -123,20 +122,18 @@ static int check_itimer(int which) ...@@ -123,20 +122,18 @@ static int check_itimer(int which)
err = gettimeofday(&end, NULL); err = gettimeofday(&end, NULL);
if (err < 0) { if (err < 0) {
perror("Can't call gettimeofday()\n"); ksft_perror("Can't call gettimeofday()");
return -1; return -1;
} }
if (!check_diff(start, end)) ksft_test_result(check_diff(start, end) == 0, "%s\n", name);
printf("[OK]\n");
else
printf("[FAIL]\n");
return 0; return 0;
} }
static int check_timer_create(int which) static int check_timer_create(int which)
{ {
const char *type;
int err; int err;
timer_t id; timer_t id;
struct timeval start, end; struct timeval start, end;
...@@ -144,31 +141,32 @@ static int check_timer_create(int which) ...@@ -144,31 +141,32 @@ static int check_timer_create(int which)
.it_value.tv_sec = DELAY, .it_value.tv_sec = DELAY,
}; };
printf("Check timer_create() ");
if (which == CLOCK_THREAD_CPUTIME_ID) { if (which == CLOCK_THREAD_CPUTIME_ID) {
printf("per thread... "); type = "thread";
} else if (which == CLOCK_PROCESS_CPUTIME_ID) { } else if (which == CLOCK_PROCESS_CPUTIME_ID) {
printf("per process... "); type = "process";
} else {
ksft_print_msg("Unknown timer_create() type %d\n", which);
return -1;
} }
fflush(stdout);
done = 0; done = 0;
err = timer_create(which, NULL, &id); err = timer_create(which, NULL, &id);
if (err < 0) { if (err < 0) {
perror("Can't create timer\n"); ksft_perror("Can't create timer");
return -1; return -1;
} }
signal(SIGALRM, sig_handler); signal(SIGALRM, sig_handler);
err = gettimeofday(&start, NULL); err = gettimeofday(&start, NULL);
if (err < 0) { if (err < 0) {
perror("Can't call gettimeofday()\n"); ksft_perror("Can't call gettimeofday()");
return -1; return -1;
} }
err = timer_settime(id, 0, &val, NULL); err = timer_settime(id, 0, &val, NULL);
if (err < 0) { if (err < 0) {
perror("Can't set timer\n"); ksft_perror("Can't set timer");
return -1; return -1;
} }
...@@ -176,14 +174,12 @@ static int check_timer_create(int which) ...@@ -176,14 +174,12 @@ static int check_timer_create(int which)
err = gettimeofday(&end, NULL); err = gettimeofday(&end, NULL);
if (err < 0) { if (err < 0) {
perror("Can't call gettimeofday()\n"); ksft_perror("Can't call gettimeofday()");
return -1; return -1;
} }
if (!check_diff(start, end)) ksft_test_result(check_diff(start, end) == 0,
printf("[OK]\n"); "timer_create() per %s\n", type);
else
printf("[FAIL]\n");
return 0; return 0;
} }
...@@ -220,25 +216,25 @@ static int check_timer_distribution(void) ...@@ -220,25 +216,25 @@ static int check_timer_distribution(void)
.it_interval.tv_nsec = 1000 * 1000, .it_interval.tv_nsec = 1000 * 1000,
}; };
printf("Check timer_create() per process signal distribution... ");
fflush(stdout);
remain = nthreads + 1; /* worker threads + this thread */ remain = nthreads + 1; /* worker threads + this thread */
signal(SIGALRM, distribution_handler); signal(SIGALRM, distribution_handler);
err = timer_create(CLOCK_PROCESS_CPUTIME_ID, NULL, &id); err = timer_create(CLOCK_PROCESS_CPUTIME_ID, NULL, &id);
if (err < 0) { if (err < 0) {
perror("Can't create timer\n"); ksft_perror("Can't create timer");
return -1; return -1;
} }
err = timer_settime(id, 0, &val, NULL); err = timer_settime(id, 0, &val, NULL);
if (err < 0) { if (err < 0) {
perror("Can't set timer\n"); ksft_perror("Can't set timer");
return -1; return -1;
} }
for (i = 0; i < nthreads; i++) { for (i = 0; i < nthreads; i++) {
if (pthread_create(&threads[i], NULL, distribution_thread, NULL)) { err = pthread_create(&threads[i], NULL, distribution_thread,
perror("Can't create thread\n"); NULL);
if (err) {
ksft_print_msg("Can't create thread: %s (%d)\n",
strerror(errno), errno);
return -1; return -1;
} }
} }
...@@ -247,25 +243,30 @@ static int check_timer_distribution(void) ...@@ -247,25 +243,30 @@ static int check_timer_distribution(void)
while (__atomic_load_n(&remain, __ATOMIC_RELAXED)); while (__atomic_load_n(&remain, __ATOMIC_RELAXED));
for (i = 0; i < nthreads; i++) { for (i = 0; i < nthreads; i++) {
if (pthread_join(threads[i], NULL)) { err = pthread_join(threads[i], NULL);
perror("Can't join thread\n"); if (err) {
ksft_print_msg("Can't join thread: %s (%d)\n",
strerror(errno), errno);
return -1; return -1;
} }
} }
if (timer_delete(id)) { if (timer_delete(id)) {
perror("Can't delete timer\n"); ksft_perror("Can't delete timer");
return -1; return -1;
} }
printf("[OK]\n"); ksft_test_result_pass("check_timer_distribution\n");
return 0; return 0;
} }
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
printf("Testing posix timers. False negative may happen on CPU execution \n"); ksft_print_header();
printf("based timers if other threads run on the CPU...\n"); ksft_set_plan(6);
ksft_print_msg("Testing posix timers. False negative may happen on CPU execution \n");
ksft_print_msg("based timers if other threads run on the CPU...\n");
if (check_itimer(ITIMER_VIRTUAL) < 0) if (check_itimer(ITIMER_VIRTUAL) < 0)
return ksft_exit_fail(); return ksft_exit_fail();
...@@ -294,5 +295,5 @@ int main(int argc, char **argv) ...@@ -294,5 +295,5 @@ int main(int argc, char **argv)
if (check_timer_distribution() < 0) if (check_timer_distribution() < 0)
return ksft_exit_fail(); return ksft_exit_fail();
return ksft_exit_pass(); ksft_finished();
} }
...@@ -78,7 +78,7 @@ static int uevent_listener(unsigned long post_flags, bool expect_uevent, ...@@ -78,7 +78,7 @@ static int uevent_listener(unsigned long post_flags, bool expect_uevent,
{ {
int sk_fd, ret; int sk_fd, ret;
socklen_t sk_addr_len; socklen_t sk_addr_len;
int fret = -1, rcv_buf_sz = __UEVENT_BUFFER_SIZE; int rcv_buf_sz = __UEVENT_BUFFER_SIZE;
uint64_t sync_add = 1; uint64_t sync_add = 1;
struct sockaddr_nl sk_addr = { 0 }, rcv_addr = { 0 }; struct sockaddr_nl sk_addr = { 0 }, rcv_addr = { 0 };
char buf[__UEVENT_BUFFER_SIZE] = { 0 }; char buf[__UEVENT_BUFFER_SIZE] = { 0 };
...@@ -121,6 +121,7 @@ static int uevent_listener(unsigned long post_flags, bool expect_uevent, ...@@ -121,6 +121,7 @@ static int uevent_listener(unsigned long post_flags, bool expect_uevent,
if ((size_t)sk_addr_len != sizeof(sk_addr)) { if ((size_t)sk_addr_len != sizeof(sk_addr)) {
fprintf(stderr, "Invalid socket address size\n"); fprintf(stderr, "Invalid socket address size\n");
ret = -1;
goto on_error; goto on_error;
} }
...@@ -147,11 +148,12 @@ static int uevent_listener(unsigned long post_flags, bool expect_uevent, ...@@ -147,11 +148,12 @@ static int uevent_listener(unsigned long post_flags, bool expect_uevent,
ret = write_nointr(sync_fd, &sync_add, sizeof(sync_add)); ret = write_nointr(sync_fd, &sync_add, sizeof(sync_add));
close(sync_fd); close(sync_fd);
if (ret != sizeof(sync_add)) { if (ret != sizeof(sync_add)) {
ret = -1;
fprintf(stderr, "Failed to synchronize with parent process\n"); fprintf(stderr, "Failed to synchronize with parent process\n");
goto on_error; goto on_error;
} }
fret = 0; ret = 0;
for (;;) { for (;;) {
ssize_t r; ssize_t r;
...@@ -187,7 +189,7 @@ static int uevent_listener(unsigned long post_flags, bool expect_uevent, ...@@ -187,7 +189,7 @@ static int uevent_listener(unsigned long post_flags, bool expect_uevent,
on_error: on_error:
close(sk_fd); close(sk_fd);
return fret; return ret;
} }
int trigger_uevent(unsigned int times) int trigger_uevent(unsigned int times)
......
abi_test
dyn_test
ftrace_test
perf_test
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment