diff options
Diffstat (limited to 'tools/testing/selftests')
62 files changed, 886 insertions, 71 deletions
diff --git a/tools/testing/selftests/Makefile b/tools/testing/selftests/Makefile index 36ff2e4c7b6f..45f145c6f843 100644 --- a/tools/testing/selftests/Makefile +++ b/tools/testing/selftests/Makefile @@ -14,6 +14,7 @@ TARGETS += powerpc TARGETS += user TARGETS += sysctl TARGETS += firmware +TARGETS += ftrace TARGETS_HOTPLUG = cpu-hotplug TARGETS_HOTPLUG += memory-hotplug diff --git a/tools/testing/selftests/ftrace/Makefile b/tools/testing/selftests/ftrace/Makefile new file mode 100644 index 000000000000..76cc9f156267 --- /dev/null +++ b/tools/testing/selftests/ftrace/Makefile @@ -0,0 +1,7 @@ +all: + +run_tests: + @/bin/sh ./ftracetest || echo "ftrace selftests: [FAIL]" + +clean: + rm -rf logs/* diff --git a/tools/testing/selftests/ftrace/README b/tools/testing/selftests/ftrace/README new file mode 100644 index 000000000000..182e76fa4b82 --- /dev/null +++ b/tools/testing/selftests/ftrace/README @@ -0,0 +1,82 @@ +Linux Ftrace Testcases + +This is a collection of testcases for ftrace tracing feature in the Linux +kernel. Since ftrace exports interfaces via the debugfs, we just need +shell scripts for testing. Feel free to add new test cases. + +Running the ftrace testcases +============================ + +At first, you need to be the root user to run this script. +To run all testcases: + + $ sudo ./ftracetest + +To run specific testcases: + + # ./ftracetest test.d/basic3.tc + +Or you can also run testcases under given directory: + + # ./ftracetest test.d/kprobe/ + +Contributing new testcases +========================== + +Copy test.d/template to your testcase (whose filename must have *.tc +extension) and rewrite the test description line. + + * The working directory of the script is <debugfs>/tracing/. + + * Take care with side effects as the tests are run with root privilege. + + * The tests should not run for a long period of time (more than 1 min.) + These are to be unit tests. + + * You can add a directory for your testcases under test.d/ if needed. + + * The test cases should run on dash (busybox shell) for testing on + minimal cross-build environments. + + * Note that the tests are run with "set -e" (errexit) option. If any + command fails, the test will be terminated immediately. + + * The tests can return some result codes instead of pass or fail by + using exit_unresolved, exit_untested, exit_unsupported and exit_xfail. + +Result code +=========== + +Ftracetest supports following result codes. + + * PASS: The test succeeded as expected. The test which exits with 0 is + counted as passed test. + + * FAIL: The test failed, but was expected to succeed. The test which exits + with !0 is counted as failed test. + + * UNRESOLVED: The test produced unclear or intermidiate results. + for example, the test was interrupted + or the test depends on a previous test, which failed. + or the test was set up incorrectly + The test which is in above situation, must call exit_unresolved. + + * UNTESTED: The test was not run, currently just a placeholder. + In this case, the test must call exit_untested. + + * UNSUPPORTED: The test failed because of lack of feature. + In this case, the test must call exit_unsupported. + + * XFAIL: The test failed, and was expected to fail. + To return XFAIL, call exit_xfail from the test. + +There are some sample test scripts for result code under samples/. +You can also run samples as below: + + # ./ftracetest samples/ + +TODO +==== + + * Fancy colored output :) + diff --git a/tools/testing/selftests/ftrace/ftracetest b/tools/testing/selftests/ftrace/ftracetest new file mode 100755 index 000000000000..a8f81c782856 --- /dev/null +++ b/tools/testing/selftests/ftrace/ftracetest @@ -0,0 +1,253 @@ +#!/bin/sh + +# ftracetest - Ftrace test shell scripts +# +# Copyright (C) Hitachi Ltd., 2014 +# Written by Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com> +# +# Released under the terms of the GPL v2. + +usage() { # errno [message] +[ "$2" ] && echo $2 +echo "Usage: ftracetest [options] [testcase(s)] [testcase-directory(s)]" +echo " Options:" +echo " -h|--help Show help message" +echo " -k|--keep Keep passed test logs" +echo " -d|--debug Debug mode (trace all shell commands)" +exit $1 +} + +errexit() { # message + echo "Error: $1" 1>&2 + exit 1 +} + +# Ensuring user privilege +if [ `id -u` -ne 0 ]; then + errexit "this must be run by root user" +fi + +# Utilities +absdir() { # file_path + (cd `dirname $1`; pwd) +} + +abspath() { + echo `absdir $1`/`basename $1` +} + +find_testcases() { #directory + echo `find $1 -name \*.tc` +} + +parse_opts() { # opts + local OPT_TEST_CASES= + local OPT_TEST_DIR= + + while [ "$1" ]; do + case "$1" in + --help|-h) + usage 0 + ;; + --keep|-k) + KEEP_LOG=1 + shift 1 + ;; + --debug|-d) + DEBUG=1 + shift 1 + ;; + *.tc) + if [ -f "$1" ]; then + OPT_TEST_CASES="$OPT_TEST_CASES `abspath $1`" + shift 1 + else + usage 1 "$1 is not a testcase" + fi + ;; + *) + if [ -d "$1" ]; then + OPT_TEST_DIR=`abspath $1` + OPT_TEST_CASES="$OPT_TEST_CASES `find_testcases $OPT_TEST_DIR`" + shift 1 + else + usage 1 "Invalid option ($1)" + fi + ;; + esac + done + if [ "$OPT_TEST_CASES" ]; then + TEST_CASES=$OPT_TEST_CASES + fi +} + +# Parameters +DEBUGFS_DIR=`grep debugfs /proc/mounts | cut -f2 -d' '` +TRACING_DIR=$DEBUGFS_DIR/tracing +TOP_DIR=`absdir $0` +TEST_DIR=$TOP_DIR/test.d +TEST_CASES=`find_testcases $TEST_DIR` +LOG_DIR=$TOP_DIR/logs/`date +%Y%m%d-%H%M%S`/ +KEEP_LOG=0 +DEBUG=0 +# Parse command-line options +parse_opts $* + +[ $DEBUG -ne 0 ] && set -x + +# Verify parameters +if [ -z "$DEBUGFS_DIR" -o ! -d "$TRACING_DIR" ]; then + errexit "No ftrace directory found" +fi + +# Preparing logs +LOG_FILE=$LOG_DIR/ftracetest.log +mkdir -p $LOG_DIR || errexit "Failed to make a log directory: $LOG_DIR" +date > $LOG_FILE +prlog() { # messages + echo "$@" | tee -a $LOG_FILE +} +catlog() { #file + cat $1 | tee -a $LOG_FILE +} +prlog "=== Ftrace unit tests ===" + + +# Testcase management +# Test result codes - Dejagnu extended code +PASS=0 # The test succeeded. +FAIL=1 # The test failed, but was expected to succeed. +UNRESOLVED=2 # The test produced indeterminate results. (e.g. interrupted) +UNTESTED=3 # The test was not run, currently just a placeholder. +UNSUPPORTED=4 # The test failed because of lack of feature. +XFAIL=5 # The test failed, and was expected to fail. + +# Accumulations +PASSED_CASES= +FAILED_CASES= +UNRESOLVED_CASES= +UNTESTED_CASES= +UNSUPPORTED_CASES= +XFAILED_CASES= +UNDEFINED_CASES= +TOTAL_RESULT=0 + +CASENO=0 +testcase() { # testfile + CASENO=$((CASENO+1)) + prlog -n "[$CASENO]"`grep "^#[ \t]*description:" $1 | cut -f2 -d:` +} + +eval_result() { # retval sigval + local retval=$2 + if [ $2 -eq 0 ]; then + test $1 -ne 0 && retval=$FAIL + fi + case $retval in + $PASS) + prlog " [PASS]" + PASSED_CASES="$PASSED_CASES $CASENO" + return 0 + ;; + $FAIL) + prlog " [FAIL]" + FAILED_CASES="$FAILED_CASES $CASENO" + return 1 # this is a bug. + ;; + $UNRESOLVED) + prlog " [UNRESOLVED]" + UNRESOLVED_CASES="$UNRESOLVED_CASES $CASENO" + return 1 # this is a kind of bug.. something happened. + ;; + $UNTESTED) + prlog " [UNTESTED]" + UNTESTED_CASES="$UNTESTED_CASES $CASENO" + return 0 + ;; + $UNSUPPORTED) + prlog " [UNSUPPORTED]" + UNSUPPORTED_CASES="$UNSUPPORTED_CASES $CASENO" + return 1 # this is not a bug, but the result should be reported. + ;; + $XFAIL) + prlog " [XFAIL]" + XFAILED_CASES="$XFAILED_CASES $CASENO" + return 0 + ;; + *) + prlog " [UNDEFINED]" + UNDEFINED_CASES="$UNDEFINED_CASES $CASENO" + return 1 # this must be a test bug + ;; + esac +} + +# Signal handling for result codes +SIG_RESULT= +SIG_BASE=36 # Use realtime signals +SIG_PID=$$ + +SIG_UNRESOLVED=$((SIG_BASE + UNRESOLVED)) +exit_unresolved () { + kill -s $SIG_UNRESOLVED $SIG_PID + exit 0 +} +trap 'SIG_RESULT=$UNRESOLVED' $SIG_UNRESOLVED + +SIG_UNTESTED=$((SIG_BASE + UNTESTED)) +exit_untested () { + kill -s $SIG_UNTESTED $SIG_PID + exit 0 +} +trap 'SIG_RESULT=$UNTESTED' $SIG_UNTESTED + +SIG_UNSUPPORTED=$((SIG_BASE + UNSUPPORTED)) +exit_unsupported () { + kill -s $SIG_UNSUPPORTED $SIG_PID + exit 0 +} +trap 'SIG_RESULT=$UNSUPPORTED' $SIG_UNSUPPORTED + +SIG_XFAIL=$((SIG_BASE + XFAIL)) +exit_xfail () { + kill -s $SIG_XFAIL $SIG_PID + exit 0 +} +trap 'SIG_RESULT=$XFAIL' $SIG_XFAIL + +# Run one test case +run_test() { # testfile + local testname=`basename $1` + local testlog=`mktemp --tmpdir=$LOG_DIR ${testname}-XXXXXX.log` + testcase $1 + echo "execute: "$1 > $testlog + SIG_RESULT=0 + # setup PID and PPID, $$ is not updated. + (cd $TRACING_DIR; read PID _ < /proc/self/stat ; + set -e; set -x; . $1) >> $testlog 2>&1 + eval_result $? $SIG_RESULT + if [ $? -eq 0 ]; then + # Remove test log if the test was done as it was expected. + [ $KEEP_LOG -eq 0 ] && rm $testlog + else + catlog $testlog + TOTAL_RESULT=1 + fi +} + +# Main loop +for t in $TEST_CASES; do + run_test $t +done + +prlog "" +prlog "# of passed: " `echo $PASSED_CASES | wc -w` +prlog "# of failed: " `echo $FAILED_CASES | wc -w` +prlog "# of unresolved: " `echo $UNRESOLVED_CASES | wc -w` +prlog "# of untested: " `echo $UNTESTED_CASES | wc -w` +prlog "# of unsupported: " `echo $UNSUPPORTED_CASES | wc -w` +prlog "# of xfailed: " `echo $XFAILED_CASES | wc -w` +prlog "# of undefined(test bug): " `echo $UNDEFINED_CASES | wc -w` + +# if no error, return 0 +exit $TOTAL_RESULT diff --git a/tools/testing/selftests/ftrace/samples/fail.tc b/tools/testing/selftests/ftrace/samples/fail.tc new file mode 100644 index 000000000000..15e35b956e05 --- /dev/null +++ b/tools/testing/selftests/ftrace/samples/fail.tc @@ -0,0 +1,4 @@ +#!/bin/sh +# description: failure-case example +cat non-exist-file +echo "this is not executed" diff --git a/tools/testing/selftests/ftrace/samples/pass.tc b/tools/testing/selftests/ftrace/samples/pass.tc new file mode 100644 index 000000000000..d01549370041 --- /dev/null +++ b/tools/testing/selftests/ftrace/samples/pass.tc @@ -0,0 +1,3 @@ +#!/bin/sh +# description: pass-case example +return 0 diff --git a/tools/testing/selftests/ftrace/samples/unresolved.tc b/tools/testing/selftests/ftrace/samples/unresolved.tc new file mode 100644 index 000000000000..41e99d3358d1 --- /dev/null +++ b/tools/testing/selftests/ftrace/samples/unresolved.tc @@ -0,0 +1,4 @@ +#!/bin/sh +# description: unresolved-case example +trap exit_unresolved INT +kill -INT $PID diff --git a/tools/testing/selftests/ftrace/samples/unsupported.tc b/tools/testing/selftests/ftrace/samples/unsupported.tc new file mode 100644 index 000000000000..45910ff13328 --- /dev/null +++ b/tools/testing/selftests/ftrace/samples/unsupported.tc @@ -0,0 +1,3 @@ +#!/bin/sh +# description: unsupported-case example +exit_unsupported diff --git a/tools/testing/selftests/ftrace/samples/untested.tc b/tools/testing/selftests/ftrace/samples/untested.tc new file mode 100644 index 000000000000..35a45946ec60 --- /dev/null +++ b/tools/testing/selftests/ftrace/samples/untested.tc @@ -0,0 +1,3 @@ +#!/bin/sh +# description: untested-case example +exit_untested diff --git a/tools/testing/selftests/ftrace/samples/xfail.tc b/tools/testing/selftests/ftrace/samples/xfail.tc new file mode 100644 index 000000000000..9dd395323259 --- /dev/null +++ b/tools/testing/selftests/ftrace/samples/xfail.tc @@ -0,0 +1,3 @@ +#!/bin/sh +# description: xfail-case example +cat non-exist-file || exit_xfail diff --git a/tools/testing/selftests/ftrace/test.d/00basic/basic1.tc b/tools/testing/selftests/ftrace/test.d/00basic/basic1.tc new file mode 100644 index 000000000000..9980ff14ae44 --- /dev/null +++ b/tools/testing/selftests/ftrace/test.d/00basic/basic1.tc @@ -0,0 +1,3 @@ +#!/bin/sh +# description: Basic trace file check +test -f README -a -f trace -a -f tracing_on -a -f trace_pipe diff --git a/tools/testing/selftests/ftrace/test.d/00basic/basic2.tc b/tools/testing/selftests/ftrace/test.d/00basic/basic2.tc new file mode 100644 index 000000000000..bf9a7b037924 --- /dev/null +++ b/tools/testing/selftests/ftrace/test.d/00basic/basic2.tc @@ -0,0 +1,7 @@ +#!/bin/sh +# description: Basic test for tracers +test -f available_tracers +for t in `cat available_tracers`; do + echo $t > current_tracer +done +echo nop > current_tracer diff --git a/tools/testing/selftests/ftrace/test.d/00basic/basic3.tc b/tools/testing/selftests/ftrace/test.d/00basic/basic3.tc new file mode 100644 index 000000000000..bde6625d9785 --- /dev/null +++ b/tools/testing/selftests/ftrace/test.d/00basic/basic3.tc @@ -0,0 +1,8 @@ +#!/bin/sh +# description: Basic trace clock test +test -f trace_clock +for c in `cat trace_clock | tr -d \[\]`; do + echo $c > trace_clock + grep '\['$c'\]' trace_clock +done +echo local > trace_clock diff --git a/tools/testing/selftests/ftrace/test.d/kprobe/add_and_remove.tc b/tools/testing/selftests/ftrace/test.d/kprobe/add_and_remove.tc new file mode 100644 index 000000000000..1b8b665ab2b3 --- /dev/null +++ b/tools/testing/selftests/ftrace/test.d/kprobe/add_and_remove.tc @@ -0,0 +1,11 @@ +#!/bin/sh +# description: Kprobe dynamic event - adding and removing + +[ -f kprobe_events ] || exit_unsupported # this is configurable + +echo 0 > events/enable +echo > kprobe_events +echo p:myevent do_fork > kprobe_events +grep myevent kprobe_events +test -d events/kprobes/myevent +echo > kprobe_events diff --git a/tools/testing/selftests/ftrace/test.d/kprobe/busy_check.tc b/tools/testing/selftests/ftrace/test.d/kprobe/busy_check.tc new file mode 100644 index 000000000000..b55c84003587 --- /dev/null +++ b/tools/testing/selftests/ftrace/test.d/kprobe/busy_check.tc @@ -0,0 +1,13 @@ +#!/bin/sh +# description: Kprobe dynamic event - busy event check + +[ -f kprobe_events ] || exit_unsupported + +echo 0 > events/enable +echo > kprobe_events +echo p:myevent do_fork > kprobe_events +test -d events/kprobes/myevent +echo 1 > events/kprobes/myevent/enable +echo > kprobe_events && exit 1 # this must fail +echo 0 > events/kprobes/myevent/enable +echo > kprobe_events # this must succeed diff --git a/tools/testing/selftests/ftrace/test.d/kprobe/kprobe_args.tc b/tools/testing/selftests/ftrace/test.d/kprobe/kprobe_args.tc new file mode 100644 index 000000000000..a603d3f8db7b --- /dev/null +++ b/tools/testing/selftests/ftrace/test.d/kprobe/kprobe_args.tc @@ -0,0 +1,16 @@ +#!/bin/sh +# description: Kprobe dynamic event with arguments + +[ -f kprobe_events ] || exit_unsupported # this is configurable + +echo 0 > events/enable +echo > kprobe_events +echo 'p:testprobe do_fork $stack $stack0 +0($stack)' > kprobe_events +grep testprobe kprobe_events +test -d events/kprobes/testprobe +echo 1 > events/kprobes/testprobe/enable +( echo "forked") +echo 0 > events/kprobes/testprobe/enable +echo "-:testprobe" >> kprobe_events +test -d events/kprobes/testprobe && exit 1 || exit 0 + diff --git a/tools/testing/selftests/ftrace/test.d/kprobe/kretprobe_args.tc b/tools/testing/selftests/ftrace/test.d/kprobe/kretprobe_args.tc new file mode 100644 index 000000000000..283c29e7f7c4 --- /dev/null +++ b/tools/testing/selftests/ftrace/test.d/kprobe/kretprobe_args.tc @@ -0,0 +1,15 @@ +#!/bin/sh +# description: Kretprobe dynamic event with arguments + +[ -f kprobe_events ] || exit_unsupported # this is configurable + +echo 0 > events/enable +echo > kprobe_events +echo 'r:testprobe2 do_fork $retval' > kprobe_events +grep testprobe2 kprobe_events +test -d events/kprobes/testprobe2 +echo 1 > events/kprobes/testprobe2/enable +( echo "forked") +echo 0 > events/kprobes/testprobe2/enable +echo '-:testprobe2' >> kprobe_events +test -d events/kprobes/testprobe2 && exit 1 || exit 0 diff --git a/tools/testing/selftests/ftrace/test.d/template b/tools/testing/selftests/ftrace/test.d/template new file mode 100644 index 000000000000..5448f7abad5f --- /dev/null +++ b/tools/testing/selftests/ftrace/test.d/template @@ -0,0 +1,9 @@ +#!/bin/sh +# description: %HERE DESCRIBE WHAT THIS DOES% +# you have to add ".tc" extention for your testcase file +# Note that all tests are run with "errexit" option. + +exit 0 # Return 0 if the test is passed, otherwise return !0 +# If the test could not run because of lack of feature, call exit_unsupported +# If the test returned unclear results, call exit_unresolved +# If the test is a dummy, or a placeholder, call exit_untested diff --git a/tools/testing/selftests/memfd/Makefile b/tools/testing/selftests/memfd/Makefile index ad4ab01cd28f..b80cd10d53ba 100644 --- a/tools/testing/selftests/memfd/Makefile +++ b/tools/testing/selftests/memfd/Makefile @@ -1,38 +1,17 @@ -uname_M := $(shell uname -m 2>/dev/null || echo not) -ARCH ?= $(shell echo $(uname_M) | sed -e s/i.86/i386/) -ifeq ($(ARCH),i386) - ARCH := x86 -endif -ifeq ($(ARCH),x86_64) - ARCH := x86 -endif - CFLAGS += -D_FILE_OFFSET_BITS=64 -CFLAGS += -I../../../../arch/x86/include/generated/uapi/ -CFLAGS += -I../../../../arch/x86/include/uapi/ CFLAGS += -I../../../../include/uapi/ CFLAGS += -I../../../../include/ all: -ifeq ($(ARCH),x86) gcc $(CFLAGS) memfd_test.c -o memfd_test -else - echo "Not an x86 target, can't build memfd selftest" -endif run_tests: all -ifeq ($(ARCH),x86) gcc $(CFLAGS) memfd_test.c -o memfd_test -endif @./memfd_test || echo "memfd_test: [FAIL]" build_fuse: -ifeq ($(ARCH),x86) gcc $(CFLAGS) fuse_mnt.c `pkg-config fuse --cflags --libs` -o fuse_mnt gcc $(CFLAGS) fuse_test.c -o fuse_test -else - echo "Not an x86 target, can't build memfd selftest" -endif run_fuse: build_fuse @./run_fuse_test.sh || echo "fuse_test: [FAIL]" diff --git a/tools/testing/selftests/memfd/memfd_test.c b/tools/testing/selftests/memfd/memfd_test.c index 3634c909b1b0..0b9eafb7ab7b 100644 --- a/tools/testing/selftests/memfd/memfd_test.c +++ b/tools/testing/selftests/memfd/memfd_test.c @@ -59,9 +59,9 @@ static void mfd_fail_new(const char *name, unsigned int flags) } } -static __u64 mfd_assert_get_seals(int fd) +static unsigned int mfd_assert_get_seals(int fd) { - long r; + int r; r = fcntl(fd, F_GET_SEALS); if (r < 0) { @@ -69,50 +69,48 @@ static __u64 mfd_assert_get_seals(int fd) abort(); } - return r; + return (unsigned int)r; } -static void mfd_assert_has_seals(int fd, __u64 seals) +static void mfd_assert_has_seals(int fd, unsigned int seals) { - __u64 s; + unsigned int s; s = mfd_assert_get_seals(fd); if (s != seals) { - printf("%llu != %llu = GET_SEALS(%d)\n", - (unsigned long long)seals, (unsigned long long)s, fd); + printf("%u != %u = GET_SEALS(%d)\n", seals, s, fd); abort(); } } -static void mfd_assert_add_seals(int fd, __u64 seals) +static void mfd_assert_add_seals(int fd, unsigned int seals) { - long r; - __u64 s; + int r; + unsigned int s; s = mfd_assert_get_seals(fd); r = fcntl(fd, F_ADD_SEALS, seals); if (r < 0) { - printf("ADD_SEALS(%d, %llu -> %llu) failed: %m\n", - fd, (unsigned long long)s, (unsigned long long)seals); + printf("ADD_SEALS(%d, %u -> %u) failed: %m\n", fd, s, seals); abort(); } } -static void mfd_fail_add_seals(int fd, __u64 seals) +static void mfd_fail_add_seals(int fd, unsigned int seals) { - long r; - __u64 s; + int r; + unsigned int s; r = fcntl(fd, F_GET_SEALS); if (r < 0) s = 0; else - s = r; + s = (unsigned int)r; r = fcntl(fd, F_ADD_SEALS, seals); if (r >= 0) { - printf("ADD_SEALS(%d, %llu -> %llu) didn't fail as expected\n", - fd, (unsigned long long)s, (unsigned long long)seals); + printf("ADD_SEALS(%d, %u -> %u) didn't fail as expected\n", + fd, s, seals); abort(); } } @@ -205,7 +203,7 @@ static void mfd_fail_open(int fd, int flags, mode_t mode) sprintf(buf, "/proc/self/fd/%d", fd); r = open(buf, flags, mode); if (r >= 0) { - printf("open(%s) didn't fail as expected\n"); + printf("open(%s) didn't fail as expected\n", buf); abort(); } } diff --git a/tools/testing/selftests/powerpc/Makefile b/tools/testing/selftests/powerpc/Makefile index 74a78cedce37..f6ff90a76bd7 100644 --- a/tools/testing/selftests/powerpc/Makefile +++ b/tools/testing/selftests/powerpc/Makefile @@ -13,7 +13,7 @@ CFLAGS := -Wall -O2 -flto -Wall -Werror -DGIT_VERSION='"$(GIT_VERSION)"' -I$(CUR export CC CFLAGS -TARGETS = pmu copyloops mm tm +TARGETS = pmu copyloops mm tm primitives endif diff --git a/tools/testing/selftests/powerpc/primitives/Makefile b/tools/testing/selftests/powerpc/primitives/Makefile new file mode 100644 index 000000000000..ea737ca01732 --- /dev/null +++ b/tools/testing/selftests/powerpc/primitives/Makefile @@ -0,0 +1,17 @@ +CFLAGS += -I$(CURDIR) + +PROGS := load_unaligned_zeropad + +all: $(PROGS) + +$(PROGS): ../harness.c + +run_tests: all + @-for PROG in $(PROGS); do \ + ./$$PROG; \ + done; + +clean: + rm -f $(PROGS) *.o + +.PHONY: all run_tests clean diff --git a/tools/testing/selftests/powerpc/primitives/asm/asm-compat.h b/tools/testing/selftests/powerpc/primitives/asm/asm-compat.h new file mode 120000 index 000000000000..b14255e15a25 --- /dev/null +++ b/tools/testing/selftests/powerpc/primitives/asm/asm-compat.h @@ -0,0 +1 @@ +../.././../../../../arch/powerpc/include/asm/asm-compat.h
\ No newline at end of file diff --git a/tools/testing/selftests/powerpc/primitives/asm/ppc-opcode.h b/tools/testing/selftests/powerpc/primitives/asm/ppc-opcode.h new file mode 100644 index 000000000000..e69de29bb2d1 --- /dev/null +++ b/tools/testing/selftests/powerpc/primitives/asm/ppc-opcode.h diff --git a/tools/testing/selftests/powerpc/primitives/load_unaligned_zeropad.c b/tools/testing/selftests/powerpc/primitives/load_unaligned_zeropad.c new file mode 100644 index 000000000000..d1b647509596 --- /dev/null +++ b/tools/testing/selftests/powerpc/primitives/load_unaligned_zeropad.c @@ -0,0 +1,147 @@ +/* + * Userspace test harness for load_unaligned_zeropad. Creates two + * pages and uses mprotect to prevent access to the second page and + * a SEGV handler that walks the exception tables and runs the fixup + * routine. + * + * The results are compared against a normal load that is that is + * performed while access to the second page is enabled via mprotect. + * + * Copyright (C) 2014 Anton Blanchard <anton@au.ibm.com>, IBM + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <stdbool.h> +#include <signal.h> +#include <unistd.h> +#include <sys/mman.h> + +#define FIXUP_SECTION ".ex_fixup" + +#include "word-at-a-time.h" + +#include "utils.h" + + +static int page_size; +static char *mem_region; + +static int protect_region(void) +{ + if (mprotect(mem_region + page_size, page_size, PROT_NONE)) { + perror("mprotect"); + return 1; + } + + return 0; +} + +static int unprotect_region(void) +{ + if (mprotect(mem_region + page_size, page_size, PROT_READ|PROT_WRITE)) { + perror("mprotect"); + return 1; + } + + return 0; +} + +extern char __start___ex_table[]; +extern char __stop___ex_table[]; + +#if defined(__powerpc64__) +#define UCONTEXT_NIA(UC) (UC)->uc_mcontext.gp_regs[PT_NIP] +#elif defined(__powerpc__) +#define UCONTEXT_NIA(UC) (UC)->uc_mcontext.uc_regs->gregs[PT_NIP] +#else +#error implement UCONTEXT_NIA +#endif + +static int segv_error; + +static void segv_handler(int signr, siginfo_t *info, void *ptr) +{ + ucontext_t *uc = (ucontext_t *)ptr; + unsigned long addr = (unsigned long)info->si_addr; + unsigned long *ip = &UCONTEXT_NIA(uc); + unsigned long *ex_p = (unsigned long *)__start___ex_table; + + while (ex_p < (unsigned long *)__stop___ex_table) { + unsigned long insn, fixup; + + insn = *ex_p++; + fixup = *ex_p++; + + if (insn == *ip) { + *ip = fixup; + return; + } + } + + printf("No exception table match for NIA %lx ADDR %lx\n", *ip, addr); + segv_error++; +} + +static void setup_segv_handler(void) +{ + struct sigaction action; + + memset(&action, 0, sizeof(action)); + action.sa_sigaction = segv_handler; + action.sa_flags = SA_SIGINFO; + sigaction(SIGSEGV, &action, NULL); +} + +static int do_one_test(char *p, int page_offset) +{ + unsigned long should; + unsigned long got; + + FAIL_IF(unprotect_region()); + should = *(unsigned long *)p; + FAIL_IF(protect_region()); + + got = load_unaligned_zeropad(p); + + if (should != got) + printf("offset %u load_unaligned_zeropad returned 0x%lx, should be 0x%lx\n", page_offset, got, should); + + return 0; +} + +static int test_body(void) +{ + unsigned long i; + + page_size = getpagesize(); + mem_region = mmap(NULL, page_size * 2, PROT_READ|PROT_WRITE, + MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); + + FAIL_IF(mem_region == MAP_FAILED); + + for (i = 0; i < page_size; i++) + mem_region[i] = i; + + memset(mem_region+page_size, 0, page_size); + + setup_segv_handler(); + + for (i = 0; i < page_size; i++) + FAIL_IF(do_one_test(mem_region+i, i)); + + FAIL_IF(segv_error); + + return 0; +} + +int main(void) +{ + return test_harness(test_body, "load_unaligned_zeropad"); +} diff --git a/tools/testing/selftests/powerpc/primitives/word-at-a-time.h b/tools/testing/selftests/powerpc/primitives/word-at-a-time.h new file mode 120000 index 000000000000..eb74401b591f --- /dev/null +++ b/tools/testing/selftests/powerpc/primitives/word-at-a-time.h @@ -0,0 +1 @@ +../../../../../arch/powerpc/include/asm/word-at-a-time.h
\ No newline at end of file diff --git a/tools/testing/selftests/rcutorture/bin/config2frag.sh b/tools/testing/selftests/rcutorture/bin/config2frag.sh index 9f9ffcd427d3..56f51ae13d73 100644..100755 --- a/tools/testing/selftests/rcutorture/bin/config2frag.sh +++ b/tools/testing/selftests/rcutorture/bin/config2frag.sh @@ -1,5 +1,5 @@ -#!/bin/sh -# Usage: sh config2frag.sh < .config > configfrag +#!/bin/bash +# Usage: config2frag.sh < .config > configfrag # # Converts the "# CONFIG_XXX is not set" to "CONFIG_XXX=n" so that the # resulting file becomes a legitimate Kconfig fragment. diff --git a/tools/testing/selftests/rcutorture/bin/configcheck.sh b/tools/testing/selftests/rcutorture/bin/configcheck.sh index d686537dd55c..eee31e261bf7 100755 --- a/tools/testing/selftests/rcutorture/bin/configcheck.sh +++ b/tools/testing/selftests/rcutorture/bin/configcheck.sh @@ -1,5 +1,5 @@ -#!/bin/sh -# Usage: sh configcheck.sh .config .config-template +#!/bin/bash +# Usage: configcheck.sh .config .config-template # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by diff --git a/tools/testing/selftests/rcutorture/bin/configinit.sh b/tools/testing/selftests/rcutorture/bin/configinit.sh index 9c3f3d39b934..15f1a17ca96e 100755 --- a/tools/testing/selftests/rcutorture/bin/configinit.sh +++ b/tools/testing/selftests/rcutorture/bin/configinit.sh @@ -1,6 +1,6 @@ -#!/bin/sh +#!/bin/bash # -# sh configinit.sh config-spec-file [ build output dir ] +# Usage: configinit.sh config-spec-file [ build output dir ] # # Create a .config file from the spec file. Run from the kernel source tree. # Exits with 0 if all went well, with 1 if all went well but the config diff --git a/tools/testing/selftests/rcutorture/bin/functions.sh b/tools/testing/selftests/rcutorture/bin/functions.sh index d01b865bb100..b325470c01b3 100644 --- a/tools/testing/selftests/rcutorture/bin/functions.sh +++ b/tools/testing/selftests/rcutorture/bin/functions.sh @@ -64,6 +64,26 @@ configfrag_boot_params () { fi } +# configfrag_boot_cpus bootparam-string config-fragment-file config-cpus +# +# Decreases number of CPUs based on any maxcpus= boot parameters specified. +configfrag_boot_cpus () { + local bootargs="`configfrag_boot_params "$1" "$2"`" + local maxcpus + if echo "${bootargs}" | grep -q 'maxcpus=[0-9]' + then + maxcpus="`echo "${bootargs}" | sed -e 's/^.*maxcpus=\([0-9]*\).*$/\1/'`" + if test "$3" -gt "$maxcpus" + then + echo $maxcpus + else + echo $3 + fi + else + echo $3 + fi +} + # configfrag_hotplug_cpu config-fragment-file # # Returns 1 if the config fragment specifies hotplug CPU. diff --git a/tools/testing/selftests/rcutorture/bin/kvm-build.sh b/tools/testing/selftests/rcutorture/bin/kvm-build.sh index 7c1e56b46de4..00cb0db2643d 100755 --- a/tools/testing/selftests/rcutorture/bin/kvm-build.sh +++ b/tools/testing/selftests/rcutorture/bin/kvm-build.sh @@ -2,7 +2,7 @@ # # Build a kvm-ready Linux kernel from the tree in the current directory. # -# Usage: sh kvm-build.sh config-template build-dir more-configs +# Usage: kvm-build.sh config-template build-dir more-configs # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by diff --git a/tools/testing/selftests/rcutorture/bin/kvm-recheck-lock.sh b/tools/testing/selftests/rcutorture/bin/kvm-recheck-lock.sh index 7f1ff1a8fc4b..43f764098e50 100755 --- a/tools/testing/selftests/rcutorture/bin/kvm-recheck-lock.sh +++ b/tools/testing/selftests/rcutorture/bin/kvm-recheck-lock.sh @@ -2,7 +2,7 @@ # # Analyze a given results directory for locktorture progress. # -# Usage: sh kvm-recheck-lock.sh resdir +# Usage: kvm-recheck-lock.sh resdir # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by diff --git a/tools/testing/selftests/rcutorture/bin/kvm-recheck-rcu.sh b/tools/testing/selftests/rcutorture/bin/kvm-recheck-rcu.sh index 307c4b95f325..d6cc07fc137f 100755 --- a/tools/testing/selftests/rcutorture/bin/kvm-recheck-rcu.sh +++ b/tools/testing/selftests/rcutorture/bin/kvm-recheck-rcu.sh @@ -2,7 +2,7 @@ # # Analyze a given results directory for rcutorture progress. # -# Usage: sh kvm-recheck-rcu.sh resdir +# Usage: kvm-recheck-rcu.sh resdir # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by diff --git a/tools/testing/selftests/rcutorture/bin/kvm-recheck.sh b/tools/testing/selftests/rcutorture/bin/kvm-recheck.sh index 3f6c9b78d177..4f5b20f367a9 100755 --- a/tools/testing/selftests/rcutorture/bin/kvm-recheck.sh +++ b/tools/testing/selftests/rcutorture/bin/kvm-recheck.sh @@ -4,7 +4,7 @@ # check the build and console output for errors. Given a directory # containing results directories, this recursively checks them all. # -# Usage: sh kvm-recheck.sh resdir ... +# Usage: kvm-recheck.sh resdir ... # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by diff --git a/tools/testing/selftests/rcutorture/bin/kvm-test-1-run.sh b/tools/testing/selftests/rcutorture/bin/kvm-test-1-run.sh index 0f69dcbf9def..f6b2b4771b78 100755 --- a/tools/testing/selftests/rcutorture/bin/kvm-test-1-run.sh +++ b/tools/testing/selftests/rcutorture/bin/kvm-test-1-run.sh @@ -6,7 +6,7 @@ # Execute this in the source tree. Do not run it as a background task # because qemu does not seem to like that much. # -# Usage: sh kvm-test-1-run.sh config builddir resdir minutes qemu-args boot_args +# Usage: kvm-test-1-run.sh config builddir resdir minutes qemu-args boot_args # # qemu-args defaults to "-nographic", along with arguments specifying the # number of CPUs and other options generated from @@ -140,6 +140,7 @@ fi # Generate -smp qemu argument. qemu_args="-nographic $qemu_args" cpu_count=`configNR_CPUS.sh $config_template` +cpu_count=`configfrag_boot_cpus "$boot_args" "$config_template" "$cpu_count"` vcpus=`identify_qemu_vcpus` if test $cpu_count -gt $vcpus then @@ -214,7 +215,7 @@ then fi if test $kruntime -ge $((seconds + grace)) then - echo "!!! Hang at $kruntime vs. $seconds seconds" >> $resdir/Warnings 2>&1 + echo "!!! PID $qemu_pid hung at $kruntime vs. $seconds seconds" >> $resdir/Warnings 2>&1 kill -KILL $qemu_pid break fi diff --git a/tools/testing/selftests/rcutorture/bin/kvm.sh b/tools/testing/selftests/rcutorture/bin/kvm.sh index 589e9c38413b..e527dc952eb0 100644..100755 --- a/tools/testing/selftests/rcutorture/bin/kvm.sh +++ b/tools/testing/selftests/rcutorture/bin/kvm.sh @@ -7,7 +7,7 @@ # Edit the definitions below to set the locations of the various directories, # as well as the test duration. # -# Usage: sh kvm.sh [ options ] +# Usage: kvm.sh [ options ] # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -188,7 +188,9 @@ for CF in $configs do if test -f "$CONFIGFRAG/$kversion/$CF" then - echo $CF `configNR_CPUS.sh $CONFIGFRAG/$kversion/$CF` >> $T/cfgcpu + cpu_count=`configNR_CPUS.sh $CONFIGFRAG/$kversion/$CF` + cpu_count=`configfrag_boot_cpus "$TORTURE_BOOTARGS" "$CONFIGFRAG/$kversion/$CF" "$cpu_count"` + echo $CF $cpu_count >> $T/cfgcpu else echo "The --configs file $CF does not exist, terminating." exit 1 diff --git a/tools/testing/selftests/rcutorture/bin/parse-build.sh b/tools/testing/selftests/rcutorture/bin/parse-build.sh index 543230951c38..499d1e598e42 100755 --- a/tools/testing/selftests/rcutorture/bin/parse-build.sh +++ b/tools/testing/selftests/rcutorture/bin/parse-build.sh @@ -1,4 +1,4 @@ -#!/bin/sh +#!/bin/bash # # Check the build output from an rcutorture run for goodness. # The "file" is a pathname on the local system, and "title" is @@ -6,8 +6,7 @@ # # The file must contain kernel build output. # -# Usage: -# sh parse-build.sh file title +# Usage: parse-build.sh file title # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by diff --git a/tools/testing/selftests/rcutorture/bin/parse-console.sh b/tools/testing/selftests/rcutorture/bin/parse-console.sh index 4185d4cab32e..f962ba4cf68b 100755 --- a/tools/testing/selftests/rcutorture/bin/parse-console.sh +++ b/tools/testing/selftests/rcutorture/bin/parse-console.sh @@ -1,11 +1,10 @@ -#!/bin/sh +#!/bin/bash # # Check the console output from an rcutorture run for oopses. # The "file" is a pathname on the local system, and "title" is # a text string for error-message purposes. # -# Usage: -# sh parse-console.sh file title +# Usage: parse-console.sh file title # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -33,6 +32,10 @@ title="$2" . functions.sh +if grep -Pq '\x00' < $file +then + print_warning Console output contains nul bytes, old qemu still running? +fi egrep 'Badness|WARNING:|Warn|BUG|===========|Call Trace:|Oops:' < $file | grep -v 'ODEBUG: ' | grep -v 'Warning: unable to open an initial console' > $T if test -s $T then diff --git a/tools/testing/selftests/rcutorture/bin/parse-torture.sh b/tools/testing/selftests/rcutorture/bin/parse-torture.sh index 3455560ab4e4..e3c5f0705696 100755 --- a/tools/testing/selftests/rcutorture/bin/parse-torture.sh +++ b/tools/testing/selftests/rcutorture/bin/parse-torture.sh @@ -1,4 +1,4 @@ -#!/bin/sh +#!/bin/bash # # Check the console output from a torture run for goodness. # The "file" is a pathname on the local system, and "title" is @@ -7,8 +7,7 @@ # The file must contain torture output, but can be interspersed # with other dmesg text, as in console-log output. # -# Usage: -# sh parse-torture.sh file title +# Usage: parse-torture.sh file title # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by diff --git a/tools/testing/selftests/rcutorture/configs/lock/CFLIST b/tools/testing/selftests/rcutorture/configs/lock/CFLIST index a061b22d1892..6910b7370761 100644 --- a/tools/testing/selftests/rcutorture/configs/lock/CFLIST +++ b/tools/testing/selftests/rcutorture/configs/lock/CFLIST @@ -1 +1,4 @@ LOCK01 +LOCK02 +LOCK03 +LOCK04
\ No newline at end of file diff --git a/tools/testing/selftests/rcutorture/configs/lock/LOCK02 b/tools/testing/selftests/rcutorture/configs/lock/LOCK02 new file mode 100644 index 000000000000..1d1da1477fc3 --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/lock/LOCK02 @@ -0,0 +1,6 @@ +CONFIG_SMP=y +CONFIG_NR_CPUS=4 +CONFIG_HOTPLUG_CPU=y +CONFIG_PREEMPT_NONE=n +CONFIG_PREEMPT_VOLUNTARY=n +CONFIG_PREEMPT=y diff --git a/tools/testing/selftests/rcutorture/configs/lock/LOCK02.boot b/tools/testing/selftests/rcutorture/configs/lock/LOCK02.boot new file mode 100644 index 000000000000..5aa44b4f1b51 --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/lock/LOCK02.boot @@ -0,0 +1 @@ +locktorture.torture_type=mutex_lock diff --git a/tools/testing/selftests/rcutorture/configs/lock/LOCK03 b/tools/testing/selftests/rcutorture/configs/lock/LOCK03 new file mode 100644 index 000000000000..1d1da1477fc3 --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/lock/LOCK03 @@ -0,0 +1,6 @@ +CONFIG_SMP=y +CONFIG_NR_CPUS=4 +CONFIG_HOTPLUG_CPU=y +CONFIG_PREEMPT_NONE=n +CONFIG_PREEMPT_VOLUNTARY=n +CONFIG_PREEMPT=y diff --git a/tools/testing/selftests/rcutorture/configs/lock/LOCK03.boot b/tools/testing/selftests/rcutorture/configs/lock/LOCK03.boot new file mode 100644 index 000000000000..a67bbe0245c9 --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/lock/LOCK03.boot @@ -0,0 +1 @@ +locktorture.torture_type=rwsem_lock diff --git a/tools/testing/selftests/rcutorture/configs/lock/LOCK04 b/tools/testing/selftests/rcutorture/configs/lock/LOCK04 new file mode 100644 index 000000000000..1d1da1477fc3 --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/lock/LOCK04 @@ -0,0 +1,6 @@ +CONFIG_SMP=y +CONFIG_NR_CPUS=4 +CONFIG_HOTPLUG_CPU=y +CONFIG_PREEMPT_NONE=n +CONFIG_PREEMPT_VOLUNTARY=n +CONFIG_PREEMPT=y diff --git a/tools/testing/selftests/rcutorture/configs/lock/LOCK04.boot b/tools/testing/selftests/rcutorture/configs/lock/LOCK04.boot new file mode 100644 index 000000000000..48c04fe47fb4 --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/lock/LOCK04.boot @@ -0,0 +1 @@ +locktorture.torture_type=rw_lock diff --git a/tools/testing/selftests/rcutorture/configs/lock/ver_functions.sh b/tools/testing/selftests/rcutorture/configs/lock/ver_functions.sh index 9746ea1cd6c7..252aae618984 100644 --- a/tools/testing/selftests/rcutorture/configs/lock/ver_functions.sh +++ b/tools/testing/selftests/rcutorture/configs/lock/ver_functions.sh @@ -38,6 +38,6 @@ per_version_boot_params () { echo $1 `locktorture_param_onoff "$1" "$2"` \ locktorture.stat_interval=15 \ locktorture.shutdown_secs=$3 \ - locktorture.locktorture_runnable=1 \ + locktorture.torture_runnable=1 \ locktorture.verbose=1 } diff --git a/tools/testing/selftests/rcutorture/configs/rcu/CFLIST b/tools/testing/selftests/rcutorture/configs/rcu/CFLIST index cd3d29cb0a47..a3a1a05a2b5c 100644 --- a/tools/testing/selftests/rcutorture/configs/rcu/CFLIST +++ b/tools/testing/selftests/rcutorture/configs/rcu/CFLIST @@ -11,3 +11,6 @@ SRCU-N SRCU-P TINY01 TINY02 +TASKS01 +TASKS02 +TASKS03 diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TASKS01 b/tools/testing/selftests/rcutorture/configs/rcu/TASKS01 new file mode 100644 index 000000000000..97f0a0b27ef7 --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/rcu/TASKS01 @@ -0,0 +1,9 @@ +CONFIG_SMP=y +CONFIG_NR_CPUS=2 +CONFIG_HOTPLUG_CPU=y +CONFIG_PREEMPT_NONE=n +CONFIG_PREEMPT_VOLUNTARY=n +CONFIG_PREEMPT=y +CONFIG_DEBUG_LOCK_ALLOC=y +CONFIG_PROVE_RCU=y +CONFIG_TASKS_RCU=y diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TASKS01.boot b/tools/testing/selftests/rcutorture/configs/rcu/TASKS01.boot new file mode 100644 index 000000000000..cd2a188eeb6d --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/rcu/TASKS01.boot @@ -0,0 +1 @@ +rcutorture.torture_type=tasks diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TASKS02 b/tools/testing/selftests/rcutorture/configs/rcu/TASKS02 new file mode 100644 index 000000000000..696d2ea74d13 --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/rcu/TASKS02 @@ -0,0 +1,5 @@ +CONFIG_SMP=n +CONFIG_PREEMPT_NONE=y +CONFIG_PREEMPT_VOLUNTARY=n +CONFIG_PREEMPT=n +CONFIG_TASKS_RCU=y diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TASKS02.boot b/tools/testing/selftests/rcutorture/configs/rcu/TASKS02.boot new file mode 100644 index 000000000000..cd2a188eeb6d --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/rcu/TASKS02.boot @@ -0,0 +1 @@ +rcutorture.torture_type=tasks diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TASKS03 b/tools/testing/selftests/rcutorture/configs/rcu/TASKS03 new file mode 100644 index 000000000000..9c60da5b5d1d --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/rcu/TASKS03 @@ -0,0 +1,13 @@ +CONFIG_SMP=y +CONFIG_NR_CPUS=2 +CONFIG_HOTPLUG_CPU=n +CONFIG_SUSPEND=n +CONFIG_HIBERNATION=n +CONFIG_PREEMPT_NONE=n +CONFIG_PREEMPT_VOLUNTARY=n +CONFIG_PREEMPT=y +CONFIG_TASKS_RCU=y +CONFIG_HZ_PERIODIC=n +CONFIG_NO_HZ_IDLE=n +CONFIG_NO_HZ_FULL=y +CONFIG_NO_HZ_FULL_ALL=y diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TASKS03.boot b/tools/testing/selftests/rcutorture/configs/rcu/TASKS03.boot new file mode 100644 index 000000000000..cd2a188eeb6d --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/rcu/TASKS03.boot @@ -0,0 +1 @@ +rcutorture.torture_type=tasks diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TREE01 b/tools/testing/selftests/rcutorture/configs/rcu/TREE01 index 063b7079c621..38e3895759dd 100644 --- a/tools/testing/selftests/rcutorture/configs/rcu/TREE01 +++ b/tools/testing/selftests/rcutorture/configs/rcu/TREE01 @@ -1,5 +1,4 @@ CONFIG_SMP=y -CONFIG_NR_CPUS=8 CONFIG_PREEMPT_NONE=n CONFIG_PREEMPT_VOLUNTARY=n CONFIG_PREEMPT=y @@ -10,8 +9,7 @@ CONFIG_NO_HZ_FULL=n CONFIG_RCU_FAST_NO_HZ=y CONFIG_RCU_TRACE=y CONFIG_HOTPLUG_CPU=y -CONFIG_RCU_FANOUT=8 -CONFIG_RCU_FANOUT_EXACT=n +CONFIG_MAXSMP=y CONFIG_RCU_NOCB_CPU=y CONFIG_RCU_NOCB_CPU_ZERO=y CONFIG_DEBUG_LOCK_ALLOC=n diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TREE01.boot b/tools/testing/selftests/rcutorture/configs/rcu/TREE01.boot index 0fc8a3428938..adc3abc82fb8 100644 --- a/tools/testing/selftests/rcutorture/configs/rcu/TREE01.boot +++ b/tools/testing/selftests/rcutorture/configs/rcu/TREE01.boot @@ -1 +1 @@ -rcutorture.torture_type=rcu_bh +rcutorture.torture_type=rcu_bh maxcpus=8 diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TREE07 b/tools/testing/selftests/rcutorture/configs/rcu/TREE07 index ab6225506909..8f1017666aa7 100644 --- a/tools/testing/selftests/rcutorture/configs/rcu/TREE07 +++ b/tools/testing/selftests/rcutorture/configs/rcu/TREE07 @@ -1,5 +1,6 @@ CONFIG_SMP=y CONFIG_NR_CPUS=16 +CONFIG_CPUMASK_OFFSTACK=y CONFIG_PREEMPT_NONE=y CONFIG_PREEMPT_VOLUNTARY=n CONFIG_PREEMPT=n @@ -7,7 +8,7 @@ CONFIG_PREEMPT=n CONFIG_HZ_PERIODIC=n CONFIG_NO_HZ_IDLE=n CONFIG_NO_HZ_FULL=y -CONFIG_NO_HZ_FULL_ALL=y +CONFIG_NO_HZ_FULL_ALL=n CONFIG_NO_HZ_FULL_SYSIDLE=y CONFIG_RCU_FAST_NO_HZ=n CONFIG_RCU_TRACE=y diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TREE07.boot b/tools/testing/selftests/rcutorture/configs/rcu/TREE07.boot new file mode 100644 index 000000000000..d44609937503 --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/rcu/TREE07.boot @@ -0,0 +1 @@ +nohz_full=2-9 diff --git a/tools/testing/selftests/rcutorture/configs/rcu/ver_functions.sh b/tools/testing/selftests/rcutorture/configs/rcu/ver_functions.sh index 8977d8d31b19..ffb85ed786fa 100644 --- a/tools/testing/selftests/rcutorture/configs/rcu/ver_functions.sh +++ b/tools/testing/selftests/rcutorture/configs/rcu/ver_functions.sh @@ -51,7 +51,7 @@ per_version_boot_params () { `rcutorture_param_n_barrier_cbs "$1"` \ rcutorture.stat_interval=15 \ rcutorture.shutdown_secs=$3 \ - rcutorture.rcutorture_runnable=1 \ + rcutorture.torture_runnable=1 \ rcutorture.test_no_idle_hz=1 \ rcutorture.verbose=1 } diff --git a/tools/testing/selftests/rcutorture/doc/initrd.txt b/tools/testing/selftests/rcutorture/doc/initrd.txt index 49d134c25c04..4170e714f044 100644 --- a/tools/testing/selftests/rcutorture/doc/initrd.txt +++ b/tools/testing/selftests/rcutorture/doc/initrd.txt @@ -6,6 +6,7 @@ this case. There are probably much better ways of doing this. That said, here are the commands: ------------------------------------------------------------------------ +cd tools/testing/selftests/rcutorture zcat /initrd.img > /tmp/initrd.img.zcat mkdir initrd cd initrd diff --git a/tools/testing/selftests/vm/Makefile b/tools/testing/selftests/vm/Makefile index 3f94e1afd6cf..4c4b1f631ecf 100644 --- a/tools/testing/selftests/vm/Makefile +++ b/tools/testing/selftests/vm/Makefile @@ -3,6 +3,7 @@ CC = $(CROSS_COMPILE)gcc CFLAGS = -Wall BINARIES = hugepage-mmap hugepage-shm map_hugetlb thuge-gen hugetlbfstest +BINARIES += transhuge-stress all: $(BINARIES) %: %.c diff --git a/tools/testing/selftests/vm/transhuge-stress.c b/tools/testing/selftests/vm/transhuge-stress.c new file mode 100644 index 000000000000..fd7f1b4a96f9 --- /dev/null +++ b/tools/testing/selftests/vm/transhuge-stress.c @@ -0,0 +1,144 @@ +/* + * Stress test for transparent huge pages, memory compaction and migration. + * + * Authors: Konstantin Khlebnikov <koct9i@gmail.com> + * + * This is free and unencumbered software released into the public domain. + */ + +#include <stdlib.h> +#include <stdio.h> +#include <stdint.h> +#include <err.h> +#include <time.h> +#include <unistd.h> +#include <fcntl.h> +#include <string.h> +#include <sys/mman.h> + +#define PAGE_SHIFT 12 +#define HPAGE_SHIFT 21 + +#define PAGE_SIZE (1 << PAGE_SHIFT) +#define HPAGE_SIZE (1 << HPAGE_SHIFT) + +#define PAGEMAP_PRESENT(ent) (((ent) & (1ull << 63)) != 0) +#define PAGEMAP_PFN(ent) ((ent) & ((1ull << 55) - 1)) + +int pagemap_fd; + +int64_t allocate_transhuge(void *ptr) +{ + uint64_t ent[2]; + + /* drop pmd */ + if (mmap(ptr, HPAGE_SIZE, PROT_READ | PROT_WRITE, + MAP_FIXED | MAP_ANONYMOUS | + MAP_NORESERVE | MAP_PRIVATE, -1, 0) != ptr) + errx(2, "mmap transhuge"); + + if (madvise(ptr, HPAGE_SIZE, MADV_HUGEPAGE)) + err(2, "MADV_HUGEPAGE"); + + /* allocate transparent huge page */ + *(volatile void **)ptr = ptr; + + if (pread(pagemap_fd, ent, sizeof(ent), + (uintptr_t)ptr >> (PAGE_SHIFT - 3)) != sizeof(ent)) + err(2, "read pagemap"); + + if (PAGEMAP_PRESENT(ent[0]) && PAGEMAP_PRESENT(ent[1]) && + PAGEMAP_PFN(ent[0]) + 1 == PAGEMAP_PFN(ent[1]) && + !(PAGEMAP_PFN(ent[0]) & ((1 << (HPAGE_SHIFT - PAGE_SHIFT)) - 1))) + return PAGEMAP_PFN(ent[0]); + + return -1; +} + +int main(int argc, char **argv) +{ + size_t ram, len; + void *ptr, *p; + struct timespec a, b; + double s; + uint8_t *map; + size_t map_len; + + ram = sysconf(_SC_PHYS_PAGES); + if (ram > SIZE_MAX / sysconf(_SC_PAGESIZE) / 4) + ram = SIZE_MAX / 4; + else + ram *= sysconf(_SC_PAGESIZE); + + if (argc == 1) + len = ram; + else if (!strcmp(argv[1], "-h")) + errx(1, "usage: %s [size in MiB]", argv[0]); + else + len = atoll(argv[1]) << 20; + + warnx("allocate %zd transhuge pages, using %zd MiB virtual memory" + " and %zd MiB of ram", len >> HPAGE_SHIFT, len >> 20, + len >> (20 + HPAGE_SHIFT - PAGE_SHIFT - 1)); + + pagemap_fd = open("/proc/self/pagemap", O_RDONLY); + if (pagemap_fd < 0) + err(2, "open pagemap"); + + len -= len % HPAGE_SIZE; + ptr = mmap(NULL, len + HPAGE_SIZE, PROT_READ | PROT_WRITE, + MAP_ANONYMOUS | MAP_NORESERVE | MAP_PRIVATE, -1, 0); + if (ptr == MAP_FAILED) + err(2, "initial mmap"); + ptr += HPAGE_SIZE - (uintptr_t)ptr % HPAGE_SIZE; + + if (madvise(ptr, len, MADV_HUGEPAGE)) + err(2, "MADV_HUGEPAGE"); + + map_len = ram >> (HPAGE_SHIFT - 1); + map = malloc(map_len); + if (!map) + errx(2, "map malloc"); + + while (1) { + int nr_succeed = 0, nr_failed = 0, nr_pages = 0; + + memset(map, 0, map_len); + + clock_gettime(CLOCK_MONOTONIC, &a); + for (p = ptr; p < ptr + len; p += HPAGE_SIZE) { + int64_t pfn; + + pfn = allocate_transhuge(p); + + if (pfn < 0) { + nr_failed++; + } else { + size_t idx = pfn >> (HPAGE_SHIFT - PAGE_SHIFT); + + nr_succeed++; + if (idx >= map_len) { + map = realloc(map, idx + 1); + if (!map) + errx(2, "map realloc"); + memset(map + map_len, 0, idx + 1 - map_len); + map_len = idx + 1; + } + if (!map[idx]) + nr_pages++; + map[idx] = 1; + } + + /* split transhuge page, keep last page */ + if (madvise(p, HPAGE_SIZE - PAGE_SIZE, MADV_DONTNEED)) + err(2, "MADV_DONTNEED"); + } + clock_gettime(CLOCK_MONOTONIC, &b); + s = b.tv_sec - a.tv_sec + (b.tv_nsec - a.tv_nsec) / 1000000000.; + + warnx("%.3f s/loop, %.3f ms/page, %10.3f MiB/s\t" + "%4d succeed, %4d failed, %4d different pages", + s, s * 1000 / (len >> HPAGE_SHIFT), len / s / (1 << 20), + nr_succeed, nr_failed, nr_pages); + } +} |