linux_kselftest-next-6.7-rc1

This kselftest update for Linux 6.7-rc1 consists of:
 
 -- 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
 
 Bulk of the patches are for resctrl fixes and enhancements.
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEEPZKym/RZuOCGeA/kCwJExA0NQxwFAmVCoHMACgkQCwJExA0N
 QxwzrA//ehiiLdV2lyghzPpDTVY8jKlB1xIpg3s0r0M3m/j6nAdnOgOe2gkapT7T
 gFGL0r7xL9crqFdymwDANLSvNWOeghqB1oIok9Ruw5Rl3FcLnkh920bE6tPsddJg
 9+/KqtZvL0Sr43l9OSgX2Uzqyw60wRQwpO0431hmgnKjblk8Rh4GZ7fUCLLNf4Ia
 yOq1s2/cdmEwRc96lDaBWZaOTusejwh/xy8tgAjozHipLsmsexbyyHVWJWkVhMOD
 ZklCtrq4lckRz+Vky6akvjoL6Mjl//7pg323e2fUcDCQxQvqwnCo2VqqyOVBnN2A
 6XHQ6yXwh0xzCKRFgAiFhWlsKOz3wEIDrdp4dmhDkg4lw4gGJcwNke1UyX5zXYKM
 1a6R1vbQS9qQOsWf34AYKZBHruFNtUt0FJYgI43SuH+fGc0D5cU91Rz+s9QIPCwj
 8tcr5RWin8BOziDz05lxSKWRHD+3oc5qmsmGYBJhilwtvY2wNbRZNDZjiO28kiIy
 3kUWXeCtHmZE1KHK1H5v6bMC8SqUU7ukvV5WebqGpxzJ2eFPbeXcek9/AWSWOFni
 7thUg6MG3e4c/zRk8JYbmqXS/GeTkdmc3+VMXApLhTB8uSOWsnVMfJS9Zc2A1tGg
 n6NRBJFQO8t9Wm1l9XvlnC9HA/8lO/3uih+SzKn/u8KvoN96HPM=
 =JZb+
 -----END PGP SIGNATURE-----

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
  ...
This commit is contained in:
Linus Torvalds 2023-11-01 17:08:10 -10:00
commit 7dc0e9c7dd
59 changed files with 698 additions and 560 deletions

View File

@ -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
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
possible targets.
@ -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 `-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.
@ -210,7 +210,7 @@ option is supported, such as::
tests by using variables specified in `Running a subset of selftests`_
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

View File

@ -1367,8 +1367,8 @@ kselftest-%: headers FORCE
PHONY += kselftest-merge
kselftest-merge:
$(if $(wildcard $(objtree)/.config),, $(error No .config exists, config your kernel first!))
$(Q)find $(srctree)/tools/testing/selftests -name config | \
xargs $(srctree)/scripts/kconfig/merge_config.sh -m $(objtree)/.config
$(Q)find $(srctree)/tools/testing/selftests -name config -o -name config.$(UTS_MACHINE) | \
xargs $(srctree)/scripts/kconfig/merge_config.sh -y -m $(objtree)/.config
$(Q)$(MAKE) -f $(srctree)/Makefile olddefconfig
# ---------------------------------------------------------------------------

View File

@ -30,8 +30,7 @@ import getopt
import Gnuplot
from numpy import *
from decimal import *
sys.path.append('../intel_pstate_tracer')
#import intel_pstate_tracer
sys.path.append(os.path.join(os.path.dirname(__file__), "..", "intel_pstate_tracer"))
import intel_pstate_tracer as ipt
__license__ = "GPL version 2"

View File

@ -1,4 +1,4 @@
#!/bin/sh
#!/bin/bash
# SPDX-License-Identifier: GPL-2.0
# Testing and monitor the cpu desire performance, frequency, load,
@ -66,12 +66,15 @@ post_clear_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"
wget -O $git_tar $gitsource_url > /dev/null 2>&1
printf "Tar gitsource ...\n\n"
tar -xzf $git_tar
popd > /dev/null 2>&1
fi
}
@ -79,12 +82,14 @@ install_gitsource()
run_gitsource()
{
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"
cd $git_name
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
cd ..
BACKUP_DIR=$(pwd)
pushd $BACKUP_DIR > /dev/null 2>&1
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`
do

View File

@ -8,9 +8,12 @@ else
FILE_MAIN=DONE
fi
source basic.sh
source tbench.sh
source gitsource.sh
SCRIPTDIR=`dirname "$0"`
TRACER=$SCRIPTDIR/../../../power/x86/amd_pstate_tracer/amd_pstate_trace.py
source $SCRIPTDIR/basic.sh
source $SCRIPTDIR/tbench.sh
source $SCRIPTDIR/gitsource.sh
# 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/')
@ -22,6 +25,7 @@ OUTFILE=selftest
OUTFILE_TBENCH="$OUTFILE.tbench"
OUTFILE_GIT="$OUTFILE.gitsource"
PERF=/usr/bin/perf
SYSFS=
CPUROOT=
CPUFREQROOT=
@ -151,6 +155,7 @@ help()
[-p <tbench process number>]
[-l <loop times for tbench>]
[-i <amd tracer interval>]
[-b <perf binary>]
[-m <comparative test: acpi-cpufreq>]
\n"
exit 2
@ -158,7 +163,7 @@ help()
parse_arguments()
{
while getopts ho:c:t:p:l:i:m: arg
while getopts ho:c:t:p:l:i:b:m: arg
do
case $arg in
h) # --help
@ -189,6 +194,10 @@ parse_arguments()
TRACER_INTERVAL=$OPTARG
;;
b) # --perf-binary
PERF=`realpath $OPTARG`
;;
m) # --comparative-test
COMPARATIVE_TEST=$OPTARG
;;
@ -202,8 +211,8 @@ parse_arguments()
command_perf()
{
if ! command -v perf > /dev/null; then
echo $msg please install perf. >&2
if ! $PERF -v; then
echo $msg please install perf or provide perf binary path as argument >&2
exit $ksft_skip
fi
}

View File

@ -64,11 +64,11 @@ post_clear_tbench()
run_tbench()
{
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"
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`
kill $pid

View File

@ -27,7 +27,7 @@ static const char * const dev_files[] = {
void print_cachestat(struct cachestat *cs)
{
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_evicted, cs->nr_recently_evicted);
}

View File

@ -2,7 +2,7 @@
TEST_GEN_FILES := validate_cap
TEST_GEN_PROGS := test_execve
CFLAGS += -O2 -g -std=gnu99 -Wall
CFLAGS += -O2 -g -std=gnu99 -Wall $(KHDR_INCLUDES)
LDLIBS += -lcap-ng -lrt -ldl
include ../lib.mk

View File

@ -20,14 +20,6 @@
#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 pid_t mpid; /* main() pid is used to avoid duplicate test counts */

View File

@ -9,14 +9,6 @@
#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)
# define HAVE_GETAUXVAL
#endif

View File

@ -7,6 +7,7 @@
#include <inttypes.h>
#include <linux/types.h>
#include <linux/sched.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
@ -103,8 +104,8 @@ static int call_clone3(uint64_t flags, size_t size, enum test_mode test_mode)
return 0;
}
static void test_clone3(uint64_t flags, size_t size, int expected,
enum test_mode test_mode)
static bool test_clone3(uint64_t flags, size_t size, int expected,
enum test_mode test_mode)
{
int ret;
@ -114,92 +115,210 @@ static void test_clone3(uint64_t flags, size_t size, int expected,
ret = call_clone3(flags, size, test_mode);
ksft_print_msg("[%d] clone3() with flags says: %d expected %d\n",
getpid(), ret, expected);
if (ret != expected)
ksft_test_result_fail(
if (ret != expected) {
ksft_print_msg(
"[%d] Result (%d) is different than expected (%d)\n",
getpid(), ret, expected);
else
ksft_test_result_pass(
"[%d] Result (%d) matches expectation (%d)\n",
getpid(), ret, expected);
return false;
}
return true;
}
typedef bool (*filter_function)(void);
typedef size_t (*size_function)(void);
static bool not_root(void)
{
if (getuid() != 0) {
ksft_print_msg("Not running as root\n");
return true;
}
return false;
}
static size_t page_size_plus_8(void)
{
return getpagesize() + 8;
}
struct test {
const char *name;
uint64_t flags;
size_t size;
size_function size_function;
int expected;
enum test_mode test_mode;
filter_function filter;
};
static const struct test tests[] = {
{
.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,
},
};
int main(int argc, char *argv[])
{
uid_t uid = getuid();
size_t size;
int i;
ksft_print_header();
ksft_set_plan(19);
ksft_set_plan(ARRAY_SIZE(tests));
test_clone3_supported();
/* Just a simple clone3() should return 0.*/
test_clone3(0, 0, 0, CLONE3_ARGS_NO_TEST);
for (i = 0; i < ARRAY_SIZE(tests); i++) {
if (tests[i].filter && tests[i].filter()) {
ksft_test_result_skip("%s\n", tests[i].name);
continue;
}
/* 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");
if (tests[i].size_function)
size = tests[i].size_function();
else
size = tests[i].size;
/* Do a clone3() with CLONE_ARGS_SIZE_VER0. */
test_clone3(0, CLONE_ARGS_SIZE_VER0, 0, CLONE3_ARGS_NO_TEST);
ksft_print_msg("Running test '%s'\n", tests[i].name);
/* 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 */
test_clone3(0, 0, -EINVAL, CLONE3_ARGS_INVAL_EXIT_SIGNAL_BIG);
/* Do a clone3() with negative 32-bit exit_signal */
test_clone3(0, 0, -EINVAL, CLONE3_ARGS_INVAL_EXIT_SIGNAL_NEG);
/* Do a clone3() with exit_signal not fitting into CSIGNAL mask */
test_clone3(0, 0, -EINVAL, CLONE3_ARGS_INVAL_EXIT_SIGNAL_CSIG);
/* Do a clone3() with NSIG < exit_signal < CSIG */
test_clone3(0, 0, -EINVAL, CLONE3_ARGS_INVAL_EXIT_SIGNAL_NSIG);
test_clone3(0, sizeof(struct __clone_args) + 8, 0, CLONE3_ARGS_ALL_0);
test_clone3(0, sizeof(struct __clone_args) + 16, -E2BIG,
CLONE3_ARGS_ALL_0);
test_clone3(0, sizeof(struct __clone_args) * 2, -E2BIG,
CLONE3_ARGS_ALL_0);
/* Do a clone3() with > page size */
test_clone3(0, getpagesize() + 8, -E2BIG, CLONE3_ARGS_NO_TEST);
/* Do a clone3() with CLONE_ARGS_SIZE_VER0 in a new PID NS. */
if (uid == 0)
test_clone3(CLONE_NEWPID, CLONE_ARGS_SIZE_VER0, 0,
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 */
test_clone3(CLONE_NEWPID, CLONE_ARGS_SIZE_VER0 - 8, -EINVAL,
CLONE3_ARGS_NO_TEST);
/* Do a clone3() with sizeof(struct clone_args) + 8 in a new PID NS */
if (uid == 0)
test_clone3(CLONE_NEWPID, sizeof(struct __clone_args) + 8, 0,
CLONE3_ARGS_NO_TEST);
else
ksft_test_result_skip("Skipping clone3() with CLONE_NEWPID\n");
/* Do a clone3() with > page size in a new PID NS */
test_clone3(CLONE_NEWPID, getpagesize() + 8, -E2BIG,
CLONE3_ARGS_NO_TEST);
/* Do a clone3() in a new time namespace */
test_clone3(CLONE_NEWTIME, 0, 0, CLONE3_ARGS_NO_TEST);
/* Do a clone3() with exit signal (SIGCHLD) in flags */
test_clone3(SIGCHLD, 0, -EINVAL, CLONE3_ARGS_NO_TEST);
ksft_test_result(test_clone3(tests[i].flags, size,
tests[i].expected,
tests[i].test_mode),
"%s\n", tests[i].name);
}
ksft_finished();
}

View File

@ -27,9 +27,7 @@
#include "../kselftest_harness.h"
#include "clone3_selftests.h"
#ifndef MAX_PID_NS_LEVEL
#define MAX_PID_NS_LEVEL 32
#endif
static void child_exit(int ret)
{

View File

@ -16,10 +16,6 @@
#include "../kselftest.h"
#include "clone3_selftests.h"
#ifndef CLONE_CLEAR_SIGHAND
#define CLONE_CLEAR_SIGHAND 0x100000000ULL
#endif
static void nop_handler(int signo)
{
}

View File

@ -15,10 +15,6 @@
#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
#define __NR_clone3 -1
#endif
@ -32,18 +28,9 @@ struct __clone_args {
__aligned_u64 stack;
__aligned_u64 stack_size;
__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_size;
#ifndef CLONE_ARGS_SIZE_VER1
#define CLONE_ARGS_SIZE_VER1 80 /* sizeof second published struct */
#endif
__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)

View File

@ -23,9 +23,7 @@
#include "../kselftest.h"
#include "clone3_selftests.h"
#ifndef MAX_PID_NS_LEVEL
#define MAX_PID_NS_LEVEL 32
#endif
static int pipe_1[2];
static int pipe_2[2];

View File

@ -16,34 +16,6 @@
#include "../kselftest_harness.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,
unsigned int flags)
{

0
tools/testing/selftests/damon/debugfs_attrs.sh Normal file → Executable file
View File

View File

0
tools/testing/selftests/damon/debugfs_empty_targets.sh Normal file → Executable file
View File

View File

View File

0
tools/testing/selftests/damon/debugfs_schemes.sh Normal file → Executable file
View File

0
tools/testing/selftests/damon/debugfs_target_ids.sh Normal file → Executable file
View File

0
tools/testing/selftests/damon/lru_sort.sh Normal file → Executable file
View File

0
tools/testing/selftests/damon/reclaim.sh Normal file → Executable file
View File

0
tools/testing/selftests/damon/sysfs.sh Normal file → Executable file
View File

View File

View File

@ -0,0 +1 @@
dmabuf-heap

View File

@ -32,8 +32,10 @@ int main(int argc, char **argv)
rc = read(fd, buf, sizeof(buf));
if (rc != 0) {
fprintf(stderr, "Reading a new var should return EOF\n");
close(fd);
return EXIT_FAILURE;
}
close(fd);
return EXIT_SUCCESS;
}

View File

@ -23,6 +23,9 @@
#include "../kselftest.h"
#define TESTS_EXPECTED 51
#define TEST_NAME_LEN (PATH_MAX * 4)
static char longpath[2 * PATH_MAX] = "";
static char *envp[] = { "IN_TEST=yes", NULL, NULL };
static char *argv[] = { "execveat", "99", NULL };
@ -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,
int expected_errno, const char *errno_str)
{
char test_name[TEST_NAME_LEN];
int rc;
errno = 0;
printf("Check failure of execveat(%d, '%s', %d) with %s... ",
fd, path?:"(null)", flags, errno_str);
snprintf(test_name, sizeof(test_name),
"Check failure of execveat(%d, '%s', %d) with %s",
fd, path?:"(null)", flags, errno_str);
rc = execveat_(fd, path, argv, envp, flags);
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;
}
if (errno != expected_errno) {
printf("[FAIL] (expected errno %d (%s) not %d (%s)\n",
expected_errno, strerror(expected_errno),
errno, strerror(errno));
ksft_print_msg("expected errno %d (%s) not %d (%s)\n",
expected_errno, strerror(expected_errno),
errno, strerror(errno));
ksft_test_result_fail("%s\n", test_name);
return 1;
}
printf("[OK]\n");
ksft_test_result_pass("%s\n", test_name);
return 0;
}
static int check_execveat_invoked_rc(int fd, const char *path, int flags,
int expected_rc, int expected_rc2)
{
char test_name[TEST_NAME_LEN];
int status;
int rc;
pid_t child;
int pathlen = path ? strlen(path) : 0;
if (pathlen > 40)
printf("Check success of execveat(%d, '%.20s...%s', %d)... ",
fd, path, (path + pathlen - 20), flags);
snprintf(test_name, sizeof(test_name),
"Check success of execveat(%d, '%.20s...%s', %d)... ",
fd, path, (path + pathlen - 20), flags);
else
printf("Check success of execveat(%d, '%s', %d)... ",
fd, path?:"(null)", flags);
snprintf(test_name, sizeof(test_name),
"Check success of execveat(%d, '%s', %d)... ",
fd, path?:"(null)", flags);
child = fork();
if (child < 0) {
printf("[FAIL] (fork() failed)\n");
ksft_perror("fork() failed");
ksft_test_result_fail("%s\n", test_name);
return 1;
}
if (child == 0) {
/* Child: do execveat(). */
rc = execveat_(fd, path, argv, envp, flags);
printf("[FAIL]: execveat() failed, rc=%d errno=%d (%s)\n",
rc, errno, strerror(errno));
ksft_print_msg("execveat() failed, rc=%d errno=%d (%s)\n",
rc, errno, strerror(errno));
ksft_test_result_fail("%s\n", test_name);
exit(1); /* should not reach here */
}
/* Parent: wait for & check child's exit status. */
rc = waitpid(child, &status, 0);
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;
}
if (!WIFEXITED(status)) {
printf("[FAIL] (child %d did not exit cleanly, status=%08x)\n",
child, status);
ksft_print_msg("child %d did not exit cleanly, status=%08x\n",
child, status);
ksft_test_result_fail("%s\n", test_name);
return 1;
}
if ((WEXITSTATUS(status) != expected_rc) &&
(WEXITSTATUS(status) != expected_rc2)) {
printf("[FAIL] (child %d exited with %d not %d nor %d)\n",
child, WEXITSTATUS(status), expected_rc, expected_rc2);
ksft_print_msg("child %d exited with %d not %d nor %d\n",
child, WEXITSTATUS(status), expected_rc,
expected_rc2);
ksft_test_result_fail("%s\n", test_name);
return 1;
}
printf("[OK]\n");
ksft_test_result_pass("%s\n", test_name);
return 0;
}
@ -129,11 +146,9 @@ static int open_or_die(const char *filename, int flags)
{
int fd = open(filename, flags);
if (fd < 0) {
printf("Failed to open '%s'; "
if (fd < 0)
ksft_exit_fail_msg("Failed to open '%s'; "
"check prerequisites are available\n", filename);
exit(1);
}
return fd;
}
@ -162,8 +177,7 @@ static int check_execveat_pathmax(int root_dfd, const char *src, int is_script)
char *cwd = getcwd(NULL, 0);
if (!cwd) {
printf("Failed to getcwd(), errno=%d (%s)\n",
errno, strerror(errno));
ksft_perror("Failed to getcwd()");
return 2;
}
strcpy(longpath, cwd);
@ -193,12 +207,12 @@ static int check_execveat_pathmax(int root_dfd, const char *src, int is_script)
*/
fd = open(longpath, O_RDONLY);
if (fd > 0) {
printf("Invoke copy of '%s' via filename of length %zu:\n",
src, strlen(longpath));
ksft_print_msg("Invoke copy of '%s' via filename of length %zu:\n",
src, strlen(longpath));
fail += check_execveat(fd, "", AT_EMPTY_PATH);
} else {
printf("Failed to open length %zu filename, errno=%d (%s)\n",
strlen(longpath), errno, strerror(errno));
ksft_print_msg("Failed to open length %zu filename, errno=%d (%s)\n",
strlen(longpath), errno, strerror(errno));
fail++;
}
@ -405,28 +419,31 @@ int main(int argc, char **argv)
const char *in_test = getenv("IN_TEST");
if (verbose) {
printf(" invoked with:");
ksft_print_msg("invoked with:\n");
for (ii = 0; ii < argc; ii++)
printf(" [%d]='%s'", ii, argv[ii]);
printf("\n");
ksft_print_msg("\t[%d]='%s\n'", ii, argv[ii]);
}
/* Check expected environment transferred. */
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;
}
/* Use the final argument as an exit code. */
rc = atoi(argv[argc - 1]);
fflush(stdout);
exit(rc);
} else {
ksft_print_header();
ksft_set_plan(TESTS_EXPECTED);
prerequisites();
if (verbose)
envp[1] = "VERBOSE=1";
rc = run_tests();
if (rc > 0)
printf("%d tests failed\n", rc);
ksft_finished();
}
return rc;
}

View File

@ -17,10 +17,6 @@
#include <sys/wait.h>
#include <unistd.h>
#ifndef CLONE_NEWNS
# define CLONE_NEWNS 0x00020000
#endif
static char *fw_path = NULL;
static void die(char *fmt, ...)

View File

@ -28,6 +28,12 @@ s390*)
mips*)
ARG1=%r4
;;
loongarch*)
ARG1=%r4
;;
riscv*)
ARG1=%a0
;;
*)
echo "Please implement other architecture here"
exit_untested

View File

@ -31,6 +31,9 @@ mips*)
loongarch*)
ARG1=%r4
;;
riscv*)
ARG1=%a0
;;
*)
echo "Please implement other architecture here"
exit_untested

View File

@ -44,6 +44,10 @@ loongarch*)
GOODREG=%r4
BADREG=%r12
;;
riscv*)
GOODREG=%a0
BADREG=%a8
;;
*)
echo "Please implement other architecture here"
exit_untested

View File

@ -48,6 +48,7 @@
#include <stdlib.h>
#include <unistd.h>
#include <stdarg.h>
#include <string.h>
#include <stdio.h>
#endif
@ -77,6 +78,8 @@
#define KSFT_XPASS 3
#define KSFT_SKIP 4
#define __printf(a, b) __attribute__((format(printf, a, b)))
/* counters */
struct ksft_count {
unsigned int ksft_pass;
@ -129,7 +132,7 @@ static inline void ksft_print_header(void)
static inline void ksft_set_plan(unsigned int plan)
{
ksft_plan = plan;
printf("1..%d\n", ksft_plan);
printf("1..%u\n", ksft_plan);
}
static inline void ksft_print_cnts(void)
@ -137,13 +140,13 @@ static inline void ksft_print_cnts(void)
if (ksft_plan != ksft_test_num())
printf("# Planned tests != run tests (%u != %u)\n",
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_xfail, ksft_cnt.ksft_xpass,
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;
va_list args;
@ -155,7 +158,20 @@ static inline void ksft_print_msg(const char *msg, ...)
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;
va_list args;
@ -163,13 +179,13 @@ static inline void ksft_test_result_pass(const char *msg, ...)
ksft_cnt.ksft_pass++;
va_start(args, msg);
printf("ok %d ", ksft_test_num());
printf("ok %u ", ksft_test_num());
errno = saved_errno;
vprintf(msg, 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;
va_list args;
@ -177,7 +193,7 @@ static inline void ksft_test_result_fail(const char *msg, ...)
ksft_cnt.ksft_fail++;
va_start(args, msg);
printf("not ok %d ", ksft_test_num());
printf("not ok %u ", ksft_test_num());
errno = saved_errno;
vprintf(msg, args);
va_end(args);
@ -195,7 +211,7 @@ static inline void ksft_test_result_fail(const char *msg, ...)
ksft_test_result_fail(fmt, ##__VA_ARGS__);\
} 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;
va_list args;
@ -203,13 +219,13 @@ static inline void ksft_test_result_xfail(const char *msg, ...)
ksft_cnt.ksft_xfail++;
va_start(args, msg);
printf("ok %d # XFAIL ", ksft_test_num());
printf("ok %u # XFAIL ", ksft_test_num());
errno = saved_errno;
vprintf(msg, 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;
va_list args;
@ -217,14 +233,14 @@ static inline void ksft_test_result_skip(const char *msg, ...)
ksft_cnt.ksft_xskip++;
va_start(args, msg);
printf("ok %d # SKIP ", ksft_test_num());
printf("ok %u # SKIP ", ksft_test_num());
errno = saved_errno;
vprintf(msg, args);
va_end(args);
}
/* 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;
va_list args;
@ -232,7 +248,7 @@ static inline void ksft_test_result_error(const char *msg, ...)
ksft_cnt.ksft_error++;
va_start(args, msg);
printf("not ok %d # error ", ksft_test_num());
printf("not ok %u # error ", ksft_test_num());
errno = saved_errno;
vprintf(msg, args);
va_end(args);
@ -271,7 +287,7 @@ static inline int ksft_exit_fail(void)
ksft_cnt.ksft_xfail + \
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;
va_list args;
@ -298,7 +314,7 @@ static inline int ksft_exit_xpass(void)
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;
va_list args;

View File

@ -33,7 +33,7 @@ static inline int _no_printf(const char *format, ...) { return 0; }
#define pr_info(...) _no_printf(__VA_ARGS__)
#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, ...) \
do { \
if (!(f)) \
@ -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);
int test_seq_read(const char *path, char **bufp, size_t *sizep);
void test_assert(bool exp, const char *exp_str,
const char *file, unsigned int line, const char *fmt, ...)
__attribute__((format(printf, 5, 6)));
void __printf(5, 6) test_assert(bool exp, const char *exp_str,
const char *file, unsigned int line,
const char *fmt, ...);
#define TEST_ASSERT(e, fmt, ...) \
test_assert((e), #e, __FILE__, __LINE__, fmt, ##__VA_ARGS__)

View File

@ -338,7 +338,7 @@ static long long remap_region(struct config c, unsigned int threshold_mb,
char c = (char) rand();
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);
ksft_print_msg("Expected: %#x\t Got: %#x\n", c & 0xff,
((char *) dest_addr)[i] & 0xff);

View File

@ -34,7 +34,7 @@ extern int test_nr;
extern int iteration_nr;
#ifdef __GNUC__
__attribute__((format(printf, 1, 2)))
__printf(1, 2)
#endif
static inline void sigsafe_printf(const char *format, ...)
{

View File

@ -300,7 +300,7 @@ void test_openat2_flags(void)
ksft_print_msg("openat2 unexpectedly returned ");
if (fdpath)
ksft_print_msg("%d['%s'] with %X (!= %X)\n",
ksft_print_msg("%d['%s'] with %X (!= %llX)\n",
fd, fdpath, fdflags,
test->how.flags);
else

View File

@ -62,7 +62,7 @@ static void error_report(struct error *err, const char *test_name)
break;
case PIDFD_PASS:
ksft_test_result_pass("%s test: Passed\n");
ksft_test_result_pass("%s test: Passed\n", test_name);
break;
default:

View File

@ -381,13 +381,13 @@ static int test_pidfd_send_signal_syscall_support(void)
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));
ksft_print_msg("Child Thread: doing exec of sleep\n");
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));
return NULL;
}
@ -427,7 +427,7 @@ static int child_poll_exec_test(void *args)
{
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));
pthread_create(&t1, NULL, test_pidfd_poll_exec_thread, NULL);
/*
@ -480,10 +480,10 @@ static void test_pidfd_poll_exec(int use_waitpid)
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));
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;
}
@ -492,7 +492,7 @@ static int child_poll_leader_exit_test(void *args)
{
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(&t2, NULL, test_pidfd_poll_leader_exit_thread, NULL);

View File

@ -1,6 +1,6 @@
# 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)
TEST_GEN_PROGS := resctrl_tests

View File

@ -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
* and perf cache miss for the benchmark
* @param: parameters passed to cache_val()
* @span: buffer size for the benchmark
*
* 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;
char *resctrl_val = param->resctrl_val;
@ -245,7 +246,7 @@ int cat_val(struct resctrl_val_param *param)
if (ret)
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");
ret = -1;
goto pe_close;
@ -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 &&
(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);
ksft_print_msg("Percent diff=%d\n", abs((int)diff_percent));

View File

@ -41,7 +41,7 @@ static int cat_setup(struct resctrl_val_param *p)
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];
unsigned long sum_llc_perf_miss = 0;
@ -76,7 +76,7 @@ static int check_results(struct resctrl_val_param *param)
fclose(fp);
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,
get_vendor() == ARCH_INTEL, false);
}
@ -96,6 +96,7 @@ int cat_perf_miss_val(int cpu_no, int n, char *cache_type)
char cbm_mask[256];
int count_of_bits;
char pipe_message;
size_t span;
/* Get default cbm mask for L3/L2 cache */
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)
/* Set param values for parent thread which will be allocated bitmask
* 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.mongrp, "m2");
strcpy(param.filename, RESULT_FILE_NAME2);
@ -162,23 +163,17 @@ int cat_perf_miss_val(int cpu_no, int n, char *cache_type)
param.mask = l_mask_1;
strcpy(param.ctrlgrp, "c1");
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);
param.num_of_runs = 0;
param.cpu_no = sibling_cpu_no;
} else {
ret = signal_handler_register();
if (ret) {
kill(bm_pid, SIGKILL);
goto out;
}
}
remove(param.filename);
ret = cat_val(&param);
ret = cat_val(&param, span);
if (ret == 0)
ret = check_results(&param);
ret = check_results(&param, span);
if (bm_pid == 0) {
/* Tell parent that child is ready */
@ -208,10 +203,8 @@ int cat_perf_miss_val(int cpu_no, int n, char *cache_type)
}
close(pipefd[0]);
kill(bm_pid, SIGKILL);
signal_handler_unregister();
}
out:
cat_test_cleanup();
return ret;

View File

@ -27,7 +27,7 @@ static int cmt_setup(struct resctrl_val_param *p)
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];
unsigned long sum_llc_occu_resc = 0;
@ -58,7 +58,7 @@ static int check_results(struct resctrl_val_param *param, int no_of_bits)
}
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,
true, true);
}
@ -68,16 +68,17 @@ void cmt_test_cleanup(void)
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 long_mask;
char *span_str = NULL;
char cbm_mask[256];
int count_of_bits;
int ret;
if (!validate_resctrl_feature_request(CMT_STR))
return -1;
size_t span;
int ret, i;
ret = get_cbm_mask("L3", cbm_mask);
if (ret)
@ -105,24 +106,36 @@ int cmt_resctrl_val(int cpu_no, int n, char **benchmark_cmd)
.cpu_no = cpu_no,
.filename = RESULT_FILE_NAME,
.mask = ~(long_mask << n) & long_mask,
.span = cache_size * n / count_of_bits,
.num_of_runs = 0,
.setup = cmt_setup,
};
if (strcmp(benchmark_cmd[0], "fill_buf") == 0)
sprintf(benchmark_cmd[1], "%zu", param.span);
span = cache_size * n / count_of_bits;
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);
ret = resctrl_val(benchmark_cmd, &param);
ret = resctrl_val(cmd, &param);
if (ret)
goto out;
ret = check_results(&param, n);
ret = check_results(&param, span, n);
out:
cmt_test_cleanup();
free(span_str);
return ret;
}

View File

@ -12,7 +12,7 @@
#define RESULT_FILE_NAME "result_mba"
#define NUM_OF_RUNS 5
#define MAX_DIFF_PERCENT 5
#define MAX_DIFF_PERCENT 8
#define ALLOCATION_MAX 100
#define ALLOCATION_MIN 10
#define ALLOCATION_STEP 10
@ -141,7 +141,7 @@ void mba_test_cleanup(void)
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 = {
.resctrl_val = MBA_STR,
@ -149,7 +149,7 @@ int mba_schemata_change(int cpu_no, char *bw_report, char **benchmark_cmd)
.mongrp = "m1",
.cpu_no = cpu_no,
.filename = RESULT_FILE_NAME,
.bw_report = bw_report,
.bw_report = "reads",
.setup = mba_setup
};
int ret;

View File

@ -11,7 +11,7 @@
#include "resctrl.h"
#define RESULT_FILE_NAME "result_mbm"
#define MAX_DIFF_PERCENT 5
#define MAX_DIFF_PERCENT 8
#define NUM_OF_RUNS 5
static int
@ -95,7 +95,7 @@ static int mbm_setup(struct resctrl_val_param *p)
return END_OF_TESTS;
/* 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,
p->resctrl_val);
@ -109,16 +109,15 @@ void mbm_test_cleanup(void)
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 = {
.resctrl_val = MBM_STR,
.ctrlgrp = "c1",
.mongrp = "m1",
.span = span,
.cpu_no = cpu_no,
.filename = RESULT_FILE_NAME,
.bw_report = bw_report,
.bw_report = "reads",
.setup = mbm_setup
};
int ret;
@ -129,7 +128,7 @@ int mbm_bw_change(size_t span, int cpu_no, char *bw_report, char **benchmark_cmd
if (ret)
goto out;
ret = check_results(span);
ret = check_results(DEFAULT_SPAN);
out:
mbm_test_cleanup();

View File

@ -1,5 +1,4 @@
/* SPDX-License-Identifier: GPL-2.0 */
#define _GNU_SOURCE
#ifndef RESCTRL_H
#define RESCTRL_H
#include <stdio.h>
@ -28,16 +27,16 @@
#define RESCTRL_PATH "/sys/fs/resctrl"
#define PHYS_ID_PATH "/sys/devices/system/cpu/cpu"
#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_AMD 2
#define END_OF_TESTS 1
#define BENCHMARK_ARGS 64
#define DEFAULT_SPAN (250 * MB)
#define PARENT_EXIT(err_msg) \
do { \
perror(err_msg); \
@ -52,7 +51,6 @@
* @ctrlgrp: Name of the control monitor group (con_mon grp)
* @mongrp: Name of the monitor group (mon grp)
* @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
* @bw_report: Bandwidth report type (reads vs writes)
* @setup: Call back function to setup test environment
@ -62,7 +60,6 @@ struct resctrl_val_param {
char ctrlgrp[64];
char mongrp[64];
int cpu_no;
size_t span;
char filename[64];
char *bw_report;
unsigned long mask;
@ -86,10 +83,9 @@ int get_resource_id(int cpu_no, int *resource_id);
int mount_resctrlfs(void);
int umount_resctrlfs(void);
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);
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,
char *resctrl_val);
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 group_fd, unsigned long flags);
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 mbm_bw_change(size_t span, int cpu_no, char *bw_report, char **benchmark_cmd);
int resctrl_val(const char * const *benchmark_cmd, struct resctrl_val_param *param);
int mbm_bw_change(int cpu_no, const char * const *benchmark_cmd);
void tests_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);
int get_cbm_mask(char *cache_type, char *cbm_mask);
int get_cache_size(int cpu_no, char *cache_type, unsigned long *cache_size);
void ctrlc_handler(int signum, siginfo_t *info, void *ptr);
int signal_handler_register(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);
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);
void cmt_test_cleanup(void);
int get_core_sibling(int cpu_no);

View File

@ -10,9 +10,6 @@
*/
#include "resctrl.h"
#define BENCHMARK_ARGS 64
#define BENCHMARK_ARG_SIZE 64
static int detect_vendor(void)
{
FILE *inf = fopen("/proc/cpuinfo", "r");
@ -52,8 +49,8 @@ int get_vendor(void)
static void cmd_help(void)
{
printf("usage: resctrl_tests [-h] [-b \"benchmark_cmd [options]\"] [-t test list] [-n no_of_bits]\n");
printf("\t-b benchmark_cmd [options]: run specified benchmark for MBM, MBA and CMT\n");
printf("usage: resctrl_tests [-h] [-t test list] [-n no_of_bits] [-b benchmark_cmd [option]...]\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-t test list: run tests specified in the test list, ");
printf("e.g. -t mbm,mba,cmt,cat\n");
@ -70,72 +67,98 @@ void tests_cleanup(void)
cat_test_cleanup();
}
static void run_mbm_test(char **benchmark_cmd, size_t span,
int cpu_no, char *bw_report)
static int test_prepare(void)
{
int res;
res = signal_handler_register();
if (res) {
ksft_print_msg("Failed to register signal handler\n");
return res;
}
res = mount_resctrlfs();
if (res) {
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");
res = mount_resctrlfs();
if (res) {
ksft_exit_fail_msg("Failed to mount resctrl FS\n");
if (test_prepare()) {
ksft_exit_fail_msg("Abnormal failure when preparing for the test\n");
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");
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");
if ((get_vendor() == ARCH_INTEL) && res)
ksft_print_msg("Intel MBM may be inaccurate when Sub-NUMA Clustering is enabled. Check BIOS configuration.\n");
umount:
umount_resctrlfs();
cleanup:
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;
ksft_print_msg("Starting MBA Schemata change ...\n");
res = mount_resctrlfs();
if (res) {
ksft_exit_fail_msg("Failed to mount resctrl FS\n");
if (test_prepare()) {
ksft_exit_fail_msg("Abnormal failure when preparing for the test\n");
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");
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");
umount:
umount_resctrlfs();
cleanup:
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;
ksft_print_msg("Starting CMT test ...\n");
res = mount_resctrlfs();
if (res) {
ksft_exit_fail_msg("Failed to mount resctrl FS\n");
if (test_prepare()) {
ksft_exit_fail_msg("Abnormal failure when preparing for the test\n");
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");
goto umount;
goto cleanup;
}
res = cmt_resctrl_val(cpu_no, 5, benchmark_cmd);
@ -143,8 +166,8 @@ static void run_cmt_test(char **benchmark_cmd, int cpu_no)
if ((get_vendor() == ARCH_INTEL) && res)
ksft_print_msg("Intel CMT may be inaccurate when Sub-NUMA Clustering is enabled. Check BIOS configuration.\n");
umount:
umount_resctrlfs();
cleanup:
test_cleanup();
}
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");
res = mount_resctrlfs();
if (res) {
ksft_exit_fail_msg("Failed to mount resctrl FS\n");
if (test_prepare()) {
ksft_exit_fail_msg("Abnormal failure when preparing for the test\n");
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");
goto umount;
goto cleanup;
}
res = cat_perf_miss_val(cpu_no, no_of_bits, "L3");
ksft_test_result(!res, "CAT: test\n");
umount:
umount_resctrlfs();
cleanup:
test_cleanup();
}
int main(int argc, char **argv)
{
bool has_ben = false, mbm_test = true, mba_test = true, cmt_test = true;
char *benchmark_cmd[BENCHMARK_ARGS], bw_report[64], bm_type[64];
char benchmark_cmd_area[BENCHMARK_ARGS][BENCHMARK_ARG_SIZE];
int c, cpu_no = 1, argc_new = argc, i, no_of_bits = 0;
int ben_ind, ben_count, tests = 0;
size_t span = 250 * MB;
bool mbm_test = true, mba_test = true, cmt_test = true;
const char *benchmark_cmd[BENCHMARK_ARGS] = {};
int c, cpu_no = 1, i, no_of_bits = 0;
char *span_str = NULL;
bool cat_test = true;
int tests = 0;
int ret;
for (i = 0; i < argc; i++) {
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) {
while ((c = getopt(argc, argv, "ht:b:n:p:")) != -1) {
char *token;
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':
token = strtok(optarg, ",");
@ -243,6 +271,7 @@ int main(int argc, char **argv)
return -1;
}
}
last_arg:
ksft_print_header();
@ -254,29 +283,6 @@ int main(int argc, char **argv)
if (geteuid() != 0)
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())
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)
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);
if (mbm_test)
run_mbm_test(benchmark_cmd, span, cpu_no, bw_report);
run_mbm_test(benchmark_cmd, cpu_no);
if (mba_test)
run_mba_test(benchmark_cmd, cpu_no, bw_report);
run_mba_test(benchmark_cmd, cpu_no);
if (cmt_test)
run_cmt_test(benchmark_cmd, cpu_no);
@ -299,5 +318,6 @@ int main(int argc, char **argv)
if (cat_test)
run_cat_test(cpu_no, no_of_bits);
free(span_str);
ksft_finished();
}

View File

@ -468,7 +468,9 @@ pid_t bm_pid, ppid;
void ctrlc_handler(int signum, siginfo_t *info, void *ptr)
{
kill(bm_pid, SIGKILL);
/* Only kill child after bm_pid is set after fork() */
if (bm_pid)
kill(bm_pid, SIGKILL);
umount_resctrlfs();
tests_cleanup();
ksft_print_msg("Ending\n\n");
@ -482,9 +484,11 @@ void ctrlc_handler(int signum, siginfo_t *info, void *ptr)
*/
int signal_handler_register(void)
{
struct sigaction sigact;
struct sigaction sigact = {};
int ret = 0;
bm_pid = 0;
sigact.sa_sigaction = ctrlc_handler;
sigemptyset(&sigact.sa_mask);
sigact.sa_flags = SA_SIGINFO;
@ -504,7 +508,7 @@ int signal_handler_register(void)
*/
void signal_handler_unregister(void)
{
struct sigaction sigact;
struct sigaction sigact = {};
sigact.sa_handler = SIG_DFL;
sigemptyset(&sigact.sa_mask);
@ -621,6 +625,56 @@ measure_vals(struct resctrl_val_param *param, unsigned long *bw_resc_start)
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
* the benchmark
@ -629,7 +683,7 @@ measure_vals(struct resctrl_val_param *param, unsigned long *bw_resc_start)
*
* 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;
unsigned long bw_resc_start = 0;
@ -706,28 +760,30 @@ int resctrl_val(char **benchmark_cmd, struct resctrl_val_param *param)
ksft_print_msg("Benchmark PID: %d\n", bm_pid);
ret = signal_handler_register();
if (ret)
goto out;
value.sival_ptr = benchmark_cmd;
/*
* The cast removes constness but nothing mutates benchmark_cmd within
* the context of this process. At the receiving process, it becomes
* argv, which is mutable, on exec() but that's after fork() so it
* doesn't matter for the process running the tests.
*/
value.sival_ptr = (void *)benchmark_cmd;
/* Taskset benchmark to specified cpu */
ret = taskset_benchmark(bm_pid, param->cpu_no);
if (ret)
goto unregister;
goto out;
/* Write benchmark to specified control&monitoring grp in resctrl FS */
ret = write_bm_pid_to_resctrl(bm_pid, param->ctrlgrp, param->mongrp,
resctrl_val);
if (ret)
goto unregister;
goto out;
if (!strncmp(resctrl_val, MBM_STR, sizeof(MBM_STR)) ||
!strncmp(resctrl_val, MBA_STR, sizeof(MBA_STR))) {
ret = initialize_mem_bw_imc();
if (ret)
goto unregister;
goto out;
initialize_mem_bw_resctrl(param->ctrlgrp, param->mongrp,
param->cpu_no, resctrl_val);
@ -742,7 +798,7 @@ int resctrl_val(char **benchmark_cmd, struct resctrl_val_param *param)
sizeof(pipe_message)) {
perror("# failed reading message from child process");
close(pipefd[0]);
goto unregister;
goto out;
}
}
close(pipefd[0]);
@ -751,7 +807,7 @@ int resctrl_val(char **benchmark_cmd, struct resctrl_val_param *param)
if (sigqueue(bm_pid, SIGUSR1, value) == -1) {
perror("# sigqueue SIGUSR1 to child");
ret = errno;
goto unregister;
goto out;
}
/* Give benchmark enough time to fully run */
@ -780,8 +836,6 @@ int resctrl_val(char **benchmark_cmd, struct resctrl_val_param *param)
}
}
unregister:
signal_handler_unregister();
out:
kill(bm_pid, SIGKILL);

View File

@ -8,6 +8,9 @@
* Sai Praneeth Prakhya <sai.praneeth.prakhya@intel.com>,
* Fenghua Yu <fenghua.yu@intel.com>
*/
#include <fcntl.h>
#include <limits.h>
#include "resctrl.h"
static int find_resctrl_mount(char *buffer)
@ -291,58 +294,6 @@ int taskset_benchmark(pid_t bm_pid, int cpu_no)
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
* @grp_name: Name of the group
@ -488,9 +439,8 @@ out:
*/
int write_schemata(char *ctrlgrp, char *schemata, int cpu_no, char *resctrl_val)
{
char controlgroup[1024], schema[1024], reason[64];
int resource_id, ret = 0;
FILE *fp;
char controlgroup[1024], reason[128], schema[1024] = {};
int resource_id, fd, schema_len = -1, ret = 0;
if (strncmp(resctrl_val, MBA_STR, sizeof(MBA_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)
if (!strncmp(resctrl_val, CAT_STR, sizeof(CAT_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)) ||
!strncmp(resctrl_val, MBM_STR, sizeof(MBM_STR)))
sprintf(schema, "%s%d%c%s", "MB:", resource_id, '=', schemata);
fp = fopen(controlgroup, "w");
if (!fp) {
sprintf(reason, "Failed to open control group");
schema_len = snprintf(schema, sizeof(schema), "%s%d%c%s\n",
"MB:", resource_id, '=', schemata);
if (schema_len < 0 || schema_len >= sizeof(schema)) {
snprintf(reason, sizeof(reason),
"snprintf() failed with return value : %d", schema_len);
ret = -1;
goto out;
}
if (fprintf(fp, "%s\n", schema) < 0) {
sprintf(reason, "Failed to write schemata in control group");
fclose(fp);
fd = open(controlgroup, O_WRONLY);
if (fd < 0) {
snprintf(reason, sizeof(reason),
"open() failed : %s", strerror(errno));
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:
ksft_print_msg("Write schema \"%s\" to resctrl FS%s%s\n",
schema, ret ? " # " : "",
@ -604,63 +565,46 @@ char *fgrep(FILE *inf, const char *str)
/*
* 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
* returned if resctrl FS is not mounted.
* Return: True if the resource/feature is supported, else false. False is
* 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;
bool found = false;
char *res;
FILE *inf;
int ret;
if (!resctrl_val)
if (!resource)
return false;
ret = find_resctrl_mount(NULL);
if (ret)
return false;
if (!strncmp(resctrl_val, CAT_STR, sizeof(CAT_STR))) {
if (!stat(L3_PATH, &statbuf))
return true;
} else if (!strncmp(resctrl_val, MBA_STR, sizeof(MBA_STR))) {
if (!stat(MB_PATH, &statbuf))
return true;
} else if (!strncmp(resctrl_val, MBM_STR, sizeof(MBM_STR)) ||
!strncmp(resctrl_val, CMT_STR, sizeof(CMT_STR))) {
if (!stat(L3_MON_PATH, &statbuf)) {
inf = fopen(L3_MON_FEATURES_PATH, "r");
if (!inf)
return false;
snprintf(res_path, sizeof(res_path), "%s/%s", INFO_PATH, resource);
if (!strncmp(resctrl_val, CMT_STR, sizeof(CMT_STR))) {
res = fgrep(inf, "llc_occupancy");
if (res) {
found = true;
free(res);
}
}
if (stat(res_path, &statbuf))
return false;
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);
}
}
if (!feature)
return true;
return found;
snprintf(res_path, sizeof(res_path), "%s/%s/mon_features", INFO_PATH, resource);
inf = fopen(res_path, "r");
if (!inf)
return false;
res = fgrep(inf, feature);
free(res);
fclose(inf);
return !!res;
}
int filter_dmesg(void)

View File

@ -1231,7 +1231,7 @@ void *test_membarrier_worker_thread(void *arg)
}
/* 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) {
int ret;
@ -1299,22 +1299,22 @@ void *test_membarrier_manager_thread(void *arg)
test_membarrier_init_percpu_list(&list_a);
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". */
cpu_a = rand() % CPU_SETSIZE;
/*
* As list_b is "inactive", we should never see changes
* 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");
abort();
}
/* 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) &&
errno != ENXIO /* missing CPU */) {
perror("sys_membarrier");
@ -1324,27 +1324,27 @@ void *test_membarrier_manager_thread(void *arg)
* Cpu A should now only modify list_b, so the values
* 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;
/*
* As list_a is "inactive", we should never see changes
* 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");
abort();
}
/* 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) &&
errno != ENXIO /* missing CPU*/) {
perror("sys_membarrier");
abort();
}
/* 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);
@ -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);
if (ret) {
errno = ret;

View File

@ -111,7 +111,7 @@ int main(void)
/* Make sure more than the required minimum. */
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_set_plan(3);

View File

@ -6,18 +6,18 @@
ksft_skip=4
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
fi
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
fi
if /sbin/modprobe -q test_static_key_base; 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_key_base
else
@ -25,6 +25,6 @@ if /sbin/modprobe -q test_static_key_base; then
/sbin/modprobe -q -r test_static_key_base
fi
else
echo "static_key: [FAIL]"
echo "static_keys: [FAIL]"
exit 1
fi

View File

@ -0,0 +1 @@
tdx_guest_test

View File

@ -118,7 +118,7 @@ int nanosleep_lat_test(int clockid, long long ns)
clock_gettime(clockid, &end);
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;
}
@ -132,20 +132,23 @@ int nanosleep_lat_test(int clockid, long long ns)
}
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 0;
}
#define SKIPPED_CLOCK_COUNT 3
int main(int argc, char **argv)
{
long long length;
int clockid, ret;
ksft_print_header();
ksft_set_plan(NR_CLOCKIDS - CLOCK_REALTIME - SKIPPED_CLOCK_COUNT);
for (clockid = CLOCK_REALTIME; clockid < NR_CLOCKIDS; clockid++) {
/* Skip cputime clockids since nanosleep won't increment cputime */
@ -154,9 +157,6 @@ int main(int argc, char **argv)
clockid == CLOCK_HWSPECIFIC)
continue;
printf("nsleep latency %-26s ", clockstring(clockid));
fflush(stdout);
length = 10;
while (length <= (NSEC_PER_SEC * 10)) {
ret = nanosleep_lat_test(clockid, length);
@ -167,14 +167,12 @@ int main(int argc, char **argv)
}
if (ret == UNSUPPORTED) {
printf("[UNSUPPORTED]\n");
continue;
ksft_test_result_skip("%s\n", clockstring(clockid));
} else {
ksft_test_result(ret >= 0, "%s\n",
clockstring(clockid));
}
if (ret < 0) {
printf("[FAILED]\n");
return ksft_exit_fail();
}
printf("[OK]\n");
}
return ksft_exit_pass();
ksft_finished();
}

View File

@ -76,22 +76,21 @@ static int check_diff(struct timeval start, struct timeval end)
static int check_itimer(int which)
{
const char *name;
int err;
struct timeval start, end;
struct itimerval val = {
.it_value.tv_sec = DELAY,
};
printf("Check itimer ");
if (which == ITIMER_VIRTUAL)
printf("virtual... ");
name = "ITIMER_VIRTUAL";
else if (which == ITIMER_PROF)
printf("prof... ");
name = "ITIMER_PROF";
else if (which == ITIMER_REAL)
printf("real... ");
fflush(stdout);
name = "ITIMER_REAL";
else
return -1;
done = 0;
@ -104,13 +103,13 @@ static int check_itimer(int which)
err = gettimeofday(&start, NULL);
if (err < 0) {
perror("Can't call gettimeofday()\n");
ksft_perror("Can't call gettimeofday()");
return -1;
}
err = setitimer(which, &val, NULL);
if (err < 0) {
perror("Can't set timer\n");
ksft_perror("Can't set timer");
return -1;
}
@ -123,20 +122,18 @@ static int check_itimer(int which)
err = gettimeofday(&end, NULL);
if (err < 0) {
perror("Can't call gettimeofday()\n");
ksft_perror("Can't call gettimeofday()");
return -1;
}
if (!check_diff(start, end))
printf("[OK]\n");
else
printf("[FAIL]\n");
ksft_test_result(check_diff(start, end) == 0, "%s\n", name);
return 0;
}
static int check_timer_create(int which)
{
const char *type;
int err;
timer_t id;
struct timeval start, end;
@ -144,31 +141,32 @@ static int check_timer_create(int which)
.it_value.tv_sec = DELAY,
};
printf("Check timer_create() ");
if (which == CLOCK_THREAD_CPUTIME_ID) {
printf("per thread... ");
type = "thread";
} 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;
err = timer_create(which, NULL, &id);
if (err < 0) {
perror("Can't create timer\n");
ksft_perror("Can't create timer");
return -1;
}
signal(SIGALRM, sig_handler);
err = gettimeofday(&start, NULL);
if (err < 0) {
perror("Can't call gettimeofday()\n");
ksft_perror("Can't call gettimeofday()");
return -1;
}
err = timer_settime(id, 0, &val, NULL);
if (err < 0) {
perror("Can't set timer\n");
ksft_perror("Can't set timer");
return -1;
}
@ -176,14 +174,12 @@ static int check_timer_create(int which)
err = gettimeofday(&end, NULL);
if (err < 0) {
perror("Can't call gettimeofday()\n");
ksft_perror("Can't call gettimeofday()");
return -1;
}
if (!check_diff(start, end))
printf("[OK]\n");
else
printf("[FAIL]\n");
ksft_test_result(check_diff(start, end) == 0,
"timer_create() per %s\n", type);
return 0;
}
@ -220,25 +216,25 @@ static int check_timer_distribution(void)
.it_interval.tv_nsec = 1000 * 1000,
};
printf("Check timer_create() per process signal distribution... ");
fflush(stdout);
remain = nthreads + 1; /* worker threads + this thread */
signal(SIGALRM, distribution_handler);
err = timer_create(CLOCK_PROCESS_CPUTIME_ID, NULL, &id);
if (err < 0) {
perror("Can't create timer\n");
ksft_perror("Can't create timer");
return -1;
}
err = timer_settime(id, 0, &val, NULL);
if (err < 0) {
perror("Can't set timer\n");
ksft_perror("Can't set timer");
return -1;
}
for (i = 0; i < nthreads; i++) {
if (pthread_create(&threads[i], NULL, distribution_thread, NULL)) {
perror("Can't create thread\n");
err = pthread_create(&threads[i], NULL, distribution_thread,
NULL);
if (err) {
ksft_print_msg("Can't create thread: %s (%d)\n",
strerror(errno), errno);
return -1;
}
}
@ -247,25 +243,30 @@ static int check_timer_distribution(void)
while (__atomic_load_n(&remain, __ATOMIC_RELAXED));
for (i = 0; i < nthreads; i++) {
if (pthread_join(threads[i], NULL)) {
perror("Can't join thread\n");
err = pthread_join(threads[i], NULL);
if (err) {
ksft_print_msg("Can't join thread: %s (%d)\n",
strerror(errno), errno);
return -1;
}
}
if (timer_delete(id)) {
perror("Can't delete timer\n");
ksft_perror("Can't delete timer");
return -1;
}
printf("[OK]\n");
ksft_test_result_pass("check_timer_distribution\n");
return 0;
}
int main(int argc, char **argv)
{
printf("Testing posix timers. False negative may happen on CPU execution \n");
printf("based timers if other threads run on the CPU...\n");
ksft_print_header();
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)
return ksft_exit_fail();
@ -294,5 +295,5 @@ int main(int argc, char **argv)
if (check_timer_distribution() < 0)
return ksft_exit_fail();
return ksft_exit_pass();
ksft_finished();
}

View File

@ -78,7 +78,7 @@ static int uevent_listener(unsigned long post_flags, bool expect_uevent,
{
int sk_fd, ret;
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;
struct sockaddr_nl sk_addr = { 0 }, rcv_addr = { 0 };
char buf[__UEVENT_BUFFER_SIZE] = { 0 };
@ -121,6 +121,7 @@ static int uevent_listener(unsigned long post_flags, bool expect_uevent,
if ((size_t)sk_addr_len != sizeof(sk_addr)) {
fprintf(stderr, "Invalid socket address size\n");
ret = -1;
goto on_error;
}
@ -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));
close(sync_fd);
if (ret != sizeof(sync_add)) {
ret = -1;
fprintf(stderr, "Failed to synchronize with parent process\n");
goto on_error;
}
fret = 0;
ret = 0;
for (;;) {
ssize_t r;
@ -187,7 +189,7 @@ static int uevent_listener(unsigned long post_flags, bool expect_uevent,
on_error:
close(sk_fd);
return fret;
return ret;
}
int trigger_uevent(unsigned int times)

View File

@ -0,0 +1,4 @@
abi_test
dyn_test
ftrace_test
perf_test