diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2022-12-13 01:39:38 +0100 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2022-12-13 01:39:38 +0100 |
commit | 23a68d14def8247735b66a14b370b42d8fcedb47 (patch) | |
tree | ca08bf8c02aee54870a3e1630c54c765080448ab | |
parent | Merge tag 'random-6.2-rc1-for-linus' of git://git.kernel.org/pub/scm/linux/ke... (diff) | |
parent | selftests/ftrace: Use long for synthetic event probe test (diff) | |
download | linux-23a68d14def8247735b66a14b370b42d8fcedb47.tar.xz linux-23a68d14def8247735b66a14b370b42d8fcedb47.zip |
Merge tag 'linux-kselftest-next-6.2-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/shuah/linux-kselftest
Pull Kselftest updates from Shuah Khan:
"Several fixes and enhancements to existing tests and a few new tests:
- add new amd-pstate tests and fix and enhance existing ones
- add new watchdog tests and enhance existing ones to improve
coverage
- fixes to ftrace, splice_read, rtc, and efivars tests
- fixes to handle egrep obsolescence in the latest grep release
- miscellaneous spelling and SPDX fixes"
* tag 'linux-kselftest-next-6.2-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/shuah/linux-kselftest: (24 commits)
selftests/ftrace: Use long for synthetic event probe test
selftests/tpm2: Split async tests call to separate shell script runner
selftests: splice_read: Fix sysfs read cases
selftests: ftrace: Use "grep -E" instead of "egrep"
selftests: gpio: Use "grep -E" instead of "egrep"
selftests: kselftest_deps: Use "grep -E" instead of "egrep"
selftests/efivarfs: Add checking of the test return value
cpufreq: amd-pstate: fix spdxcheck warnings for amd-pstate-ut.c
selftests: rtc: skip when RTC is not present
selftests/ftrace: event_triggers: wait longer for test_event_enable
selftests/vDSO: Add riscv getcpu & gettimeofday test
Documentation: amd-pstate: Add tbench and gitsource test introduction
selftests: amd-pstate: Trigger gitsource benchmark and test cpus
selftests: amd-pstate: Trigger tbench benchmark and test cpus
selftests: amd-pstate: Split basic.sh into run.sh and basic.sh.
selftests: amd-pstate: Rename amd-pstate-ut.sh to basic.sh.
selftests/ftrace: Convert tracer tests to use 'requires' to specify program dependency
selftests/ftrace: Add check for ping command for trigger tests
selftests/watchdog: Fix spelling mistake "Temeprature" -> "Temperature"
selftests/watchdog: add test for WDIOC_GETTEMP
...
35 files changed, 1502 insertions, 121 deletions
diff --git a/Documentation/admin-guide/pm/amd-pstate.rst b/Documentation/admin-guide/pm/amd-pstate.rst index 06e23538f79c..5376d53faaa8 100644 --- a/Documentation/admin-guide/pm/amd-pstate.rst +++ b/Documentation/admin-guide/pm/amd-pstate.rst @@ -405,37 +405,55 @@ Unit Tests for amd-pstate 1. Test case decriptions + 1). Basic tests + + Test prerequisite and basic functions for the ``amd-pstate`` driver. + +---------+--------------------------------+------------------------------------------------------------------------------------+ | Index | Functions | Description | +=========+================================+====================================================================================+ - | 0 | amd_pstate_ut_acpi_cpc_valid || Check whether the _CPC object is present in SBIOS. | + | 1 | amd_pstate_ut_acpi_cpc_valid || Check whether the _CPC object is present in SBIOS. | | | || | | | || The detail refer to `Processor Support <processor_support_>`_. | +---------+--------------------------------+------------------------------------------------------------------------------------+ - | 1 | amd_pstate_ut_check_enabled || Check whether AMD P-State is enabled. | + | 2 | amd_pstate_ut_check_enabled || Check whether AMD P-State is enabled. | | | || | | | || AMD P-States and ACPI hardware P-States always can be supported in one processor. | | | | But AMD P-States has the higher priority and if it is enabled with | | | | :c:macro:`MSR_AMD_CPPC_ENABLE` or ``cppc_set_enable``, it will respond to the | | | | request from AMD P-States. | +---------+--------------------------------+------------------------------------------------------------------------------------+ - | 2 | amd_pstate_ut_check_perf || Check if the each performance values are reasonable. | + | 3 | amd_pstate_ut_check_perf || Check if the each performance values are reasonable. | | | || highest_perf >= nominal_perf > lowest_nonlinear_perf > lowest_perf > 0. | +---------+--------------------------------+------------------------------------------------------------------------------------+ - | 3 | amd_pstate_ut_check_freq || Check if the each frequency values and max freq when set support boost mode | + | 4 | amd_pstate_ut_check_freq || Check if the each frequency values and max freq when set support boost mode | | | | are reasonable. | | | || max_freq >= nominal_freq > lowest_nonlinear_freq > min_freq > 0 | | | || If boost is not active but supported, this maximum frequency will be larger than | | | | the one in ``cpuinfo``. | +---------+--------------------------------+------------------------------------------------------------------------------------+ + 2). Tbench test + + Test and monitor the cpu changes when running tbench benchmark under the specified governor. + These changes include desire performance, frequency, load, performance, energy etc. + The specified governor is ondemand or schedutil. + Tbench can also be tested on the ``acpi-cpufreq`` kernel driver for comparison. + + 3). Gitsource test + + Test and monitor the cpu changes when running gitsource benchmark under the specified governor. + These changes include desire performance, frequency, load, time, energy etc. + The specified governor is ondemand or schedutil. + Gitsource can also be tested on the ``acpi-cpufreq`` kernel driver for comparison. + #. How to execute the tests We use test module in the kselftest frameworks to implement it. - We create amd-pstate-ut module and tie it into kselftest.(for + We create ``amd-pstate-ut`` module and tie it into kselftest.(for details refer to Linux Kernel Selftests [4]_). - 1. Build + 1). Build + open the :c:macro:`CONFIG_X86_AMD_PSTATE` configuration option. + set the :c:macro:`CONFIG_X86_AMD_PSTATE_UT` configuration option to M. @@ -445,23 +463,159 @@ Unit Tests for amd-pstate $ cd linux $ make -C tools/testing/selftests - #. Installation & Steps :: + + make perf :: + + $ cd tools/perf/ + $ make + + + 2). Installation & Steps :: $ make -C tools/testing/selftests install INSTALL_PATH=~/kselftest + $ cp tools/perf/perf /usr/bin/perf $ sudo ./kselftest/run_kselftest.sh -c amd-pstate - TAP version 13 - 1..1 - # selftests: amd-pstate: amd-pstate-ut.sh - # amd-pstate-ut: ok - ok 1 selftests: amd-pstate: amd-pstate-ut.sh - - #. Results :: - - $ dmesg | grep "amd_pstate_ut" | tee log.txt - [12977.570663] amd_pstate_ut: 1 amd_pstate_ut_acpi_cpc_valid success! - [12977.570673] amd_pstate_ut: 2 amd_pstate_ut_check_enabled success! - [12977.571207] amd_pstate_ut: 3 amd_pstate_ut_check_perf success! - [12977.571212] amd_pstate_ut: 4 amd_pstate_ut_check_freq success! + + 3). Specified test case :: + + $ cd ~/kselftest/amd-pstate + $ sudo ./run.sh -t basic + $ sudo ./run.sh -t tbench + $ sudo ./run.sh -t tbench -m acpi-cpufreq + $ sudo ./run.sh -t gitsource + $ sudo ./run.sh -t gitsource -m acpi-cpufreq + $ ./run.sh --help + ./run.sh: illegal option -- - + Usage: ./run.sh [OPTION...] + [-h <help>] + [-o <output-file-for-dump>] + [-c <all: All testing, + basic: Basic testing, + tbench: Tbench testing, + gitsource: Gitsource testing.>] + [-t <tbench time limit>] + [-p <tbench process number>] + [-l <loop times for tbench>] + [-i <amd tracer interval>] + [-m <comparative test: acpi-cpufreq>] + + + 4). Results + + + basic + + When you finish test, you will get the following log info :: + + $ dmesg | grep "amd_pstate_ut" | tee log.txt + [12977.570663] amd_pstate_ut: 1 amd_pstate_ut_acpi_cpc_valid success! + [12977.570673] amd_pstate_ut: 2 amd_pstate_ut_check_enabled success! + [12977.571207] amd_pstate_ut: 3 amd_pstate_ut_check_perf success! + [12977.571212] amd_pstate_ut: 4 amd_pstate_ut_check_freq success! + + + tbench + + When you finish test, you will get selftest.tbench.csv and png images. + The selftest.tbench.csv file contains the raw data and the drop of the comparative test. + The png images shows the performance, energy and performan per watt of each test. + Open selftest.tbench.csv : + + +-------------------------------------------------+--------------+----------+---------+----------+-------------+---------+----------------------+ + + Governor | Round | Des-perf | Freq | Load | Performance | Energy | Performance Per Watt | + +-------------------------------------------------+--------------+----------+---------+----------+-------------+---------+----------------------+ + + Unit | | | GHz | | MB/s | J | MB/J | + +=================================================+==============+==========+=========+==========+=============+=========+======================+ + + amd-pstate-ondemand | 1 | | | | 2504.05 | 1563.67 | 158.5378 | + +-------------------------------------------------+--------------+----------+---------+----------+-------------+---------+----------------------+ + + amd-pstate-ondemand | 2 | | | | 2243.64 | 1430.32 | 155.2941 | + +-------------------------------------------------+--------------+----------+---------+----------+-------------+---------+----------------------+ + + amd-pstate-ondemand | 3 | | | | 2183.88 | 1401.32 | 154.2860 | + +-------------------------------------------------+--------------+----------+---------+----------+-------------+---------+----------------------+ + + amd-pstate-ondemand | Average | | | | 2310.52 | 1465.1 | 156.1268 | + +-------------------------------------------------+--------------+----------+---------+----------+-------------+---------+----------------------+ + + amd-pstate-schedutil | 1 | 165.329 | 1.62257 | 99.798 | 2136.54 | 1395.26 | 151.5971 | + +-------------------------------------------------+--------------+----------+---------+----------+-------------+---------+----------------------+ + + amd-pstate-schedutil | 2 | 166 | 1.49761 | 99.9993 | 2100.56 | 1380.5 | 150.6377 | + +-------------------------------------------------+--------------+----------+---------+----------+-------------+---------+----------------------+ + + amd-pstate-schedutil | 3 | 166 | 1.47806 | 99.9993 | 2084.12 | 1375.76 | 149.9737 | + +-------------------------------------------------+--------------+----------+---------+----------+-------------+---------+----------------------+ + + amd-pstate-schedutil | Average | 165.776 | 1.53275 | 99.9322 | 2107.07 | 1383.84 | 150.7399 | + +-------------------------------------------------+--------------+----------+---------+----------+-------------+---------+----------------------+ + + acpi-cpufreq-ondemand | 1 | | | | 2529.9 | 1564.4 | 160.0997 | + +-------------------------------------------------+--------------+----------+---------+----------+-------------+---------+----------------------+ + + acpi-cpufreq-ondemand | 2 | | | | 2249.76 | 1432.97 | 155.4297 | + +-------------------------------------------------+--------------+----------+---------+----------+-------------+---------+----------------------+ + + acpi-cpufreq-ondemand | 3 | | | | 2181.46 | 1406.88 | 153.5060 | + +-------------------------------------------------+--------------+----------+---------+----------+-------------+---------+----------------------+ + + acpi-cpufreq-ondemand | Average | | | | 2320.37 | 1468.08 | 156.4741 | + +-------------------------------------------------+--------------+----------+---------+----------+-------------+---------+----------------------+ + + acpi-cpufreq-schedutil | 1 | | | | 2137.64 | 1385.24 | 152.7723 | + +-------------------------------------------------+--------------+----------+---------+----------+-------------+---------+----------------------+ + + acpi-cpufreq-schedutil | 2 | | | | 2107.05 | 1372.23 | 152.0138 | + +-------------------------------------------------+--------------+----------+---------+----------+-------------+---------+----------------------+ + + acpi-cpufreq-schedutil | 3 | | | | 2085.86 | 1365.35 | 151.2433 | + +-------------------------------------------------+--------------+----------+---------+----------+-------------+---------+----------------------+ + + acpi-cpufreq-schedutil | Average | | | | 2110.18 | 1374.27 | 152.0136 | + +-------------------------------------------------+--------------+----------+---------+----------+-------------+---------+----------------------+ + + acpi-cpufreq-ondemand VS acpi-cpufreq-schedutil | Comprison(%) | | | | -9.0584 | -6.3899 | -2.8506 | + +-------------------------------------------------+--------------+----------+---------+----------+-------------+---------+----------------------+ + + amd-pstate-ondemand VS amd-pstate-schedutil | Comprison(%) | | | | 8.8053 | -5.5463 | -3.4503 | + +-------------------------------------------------+--------------+----------+---------+----------+-------------+---------+----------------------+ + + acpi-cpufreq-ondemand VS amd-pstate-ondemand | Comprison(%) | | | | -0.4245 | -0.2029 | -0.2219 | + +-------------------------------------------------+--------------+----------+---------+----------+-------------+---------+----------------------+ + + acpi-cpufreq-schedutil VS amd-pstate-schedutil | Comprison(%) | | | | -0.1473 | 0.6963 | -0.8378 | + +-------------------------------------------------+--------------+----------+---------+----------+-------------+---------+----------------------+ + + + gitsource + + When you finish test, you will get selftest.gitsource.csv and png images. + The selftest.gitsource.csv file contains the raw data and the drop of the comparative test. + The png images shows the performance, energy and performan per watt of each test. + Open selftest.gitsource.csv : + + +-------------------------------------------------+--------------+----------+----------+----------+-------------+---------+----------------------+ + + Governor | Round | Des-perf | Freq | Load | Time | Energy | Performance Per Watt | + +-------------------------------------------------+--------------+----------+----------+----------+-------------+---------+----------------------+ + + Unit | | | GHz | | s | J | 1/J | + +=================================================+==============+==========+==========+==========+=============+=========+======================+ + + amd-pstate-ondemand | 1 | 50.119 | 2.10509 | 23.3076 | 475.69 | 865.78 | 0.001155027 | + +-------------------------------------------------+--------------+----------+----------+----------+-------------+---------+----------------------+ + + amd-pstate-ondemand | 2 | 94.8006 | 1.98771 | 56.6533 | 467.1 | 839.67 | 0.001190944 | + +-------------------------------------------------+--------------+----------+----------+----------+-------------+---------+----------------------+ + + amd-pstate-ondemand | 3 | 76.6091 | 2.53251 | 43.7791 | 467.69 | 855.85 | 0.001168429 | + +-------------------------------------------------+--------------+----------+----------+----------+-------------+---------+----------------------+ + + amd-pstate-ondemand | Average | 73.8429 | 2.20844 | 41.2467 | 470.16 | 853.767 | 0.001171279 | + +-------------------------------------------------+--------------+----------+----------+----------+-------------+---------+----------------------+ + + amd-pstate-schedutil | 1 | 165.919 | 1.62319 | 98.3868 | 464.17 | 866.8 | 0.001153668 | + +-------------------------------------------------+--------------+----------+----------+----------+-------------+---------+----------------------+ + + amd-pstate-schedutil | 2 | 165.97 | 1.31309 | 99.5712 | 480.15 | 880.4 | 0.001135847 | + +-------------------------------------------------+--------------+----------+----------+----------+-------------+---------+----------------------+ + + amd-pstate-schedutil | 3 | 165.973 | 1.28448 | 99.9252 | 481.79 | 867.02 | 0.001153375 | + +-------------------------------------------------+--------------+----------+----------+----------+-------------+---------+----------------------+ + + amd-pstate-schedutil | Average | 165.954 | 1.40692 | 99.2944 | 475.37 | 871.407 | 0.001147569 | + +-------------------------------------------------+--------------+----------+----------+----------+-------------+---------+----------------------+ + + acpi-cpufreq-ondemand | 1 | | | | 2379.62 | 742.96 | 0.001345967 | + +-------------------------------------------------+--------------+----------+----------+----------+-------------+---------+----------------------+ + + acpi-cpufreq-ondemand | 2 | | | | 441.74 | 817.49 | 0.001223256 | + +-------------------------------------------------+--------------+----------+----------+----------+-------------+---------+----------------------+ + + acpi-cpufreq-ondemand | 3 | | | | 455.48 | 820.01 | 0.001219497 | + +-------------------------------------------------+--------------+----------+----------+----------+-------------+---------+----------------------+ + + acpi-cpufreq-ondemand | Average | | | | 425.613 | 793.487 | 0.001260260 | + +-------------------------------------------------+--------------+----------+----------+----------+-------------+---------+----------------------+ + + acpi-cpufreq-schedutil | 1 | | | | 459.69 | 838.54 | 0.001192548 | + +-------------------------------------------------+--------------+----------+----------+----------+-------------+---------+----------------------+ + + acpi-cpufreq-schedutil | 2 | | | | 466.55 | 830.89 | 0.001203528 | + +-------------------------------------------------+--------------+----------+----------+----------+-------------+---------+----------------------+ + + acpi-cpufreq-schedutil | 3 | | | | 470.38 | 837.32 | 0.001194286 | + +-------------------------------------------------+--------------+----------+----------+----------+-------------+---------+----------------------+ + + acpi-cpufreq-schedutil | Average | | | | 465.54 | 835.583 | 0.001196769 | + +-------------------------------------------------+--------------+----------+----------+----------+-------------+---------+----------------------+ + + acpi-cpufreq-ondemand VS acpi-cpufreq-schedutil | Comprison(%) | | | | 9.3810 | 5.3051 | -5.0379 | + +-------------------------------------------------+--------------+----------+----------+----------+-------------+---------+----------------------+ + + amd-pstate-ondemand VS amd-pstate-schedutil | Comprison(%) | 124.7392 | -36.2934 | 140.7329 | 1.1081 | 2.0661 | -2.0242 | + +-------------------------------------------------+--------------+----------+----------+----------+-------------+---------+----------------------+ + + acpi-cpufreq-ondemand VS amd-pstate-ondemand | Comprison(%) | | | | 10.4665 | 7.5968 | -7.0605 | + +-------------------------------------------------+--------------+----------+----------+----------+-------------+---------+----------------------+ + + acpi-cpufreq-schedutil VS amd-pstate-schedutil | Comprison(%) | | | | 2.1115 | 4.2873 | -4.1110 | + +-------------------------------------------------+--------------+----------+----------+----------+-------------+---------+----------------------+ Reference =========== diff --git a/drivers/cpufreq/amd-pstate-ut.c b/drivers/cpufreq/amd-pstate-ut.c index e4a5b4d90f83..7f3fe2048981 100644 --- a/drivers/cpufreq/amd-pstate-ut.c +++ b/drivers/cpufreq/amd-pstate-ut.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-1.0-or-later +// SPDX-License-Identifier: GPL-2.0-or-later /* * AMD Processor P-state Frequency Driver Unit Test * diff --git a/tools/testing/selftests/amd-pstate/Makefile b/tools/testing/selftests/amd-pstate/Makefile index 199867f44b32..5f195ee756d6 100644 --- a/tools/testing/selftests/amd-pstate/Makefile +++ b/tools/testing/selftests/amd-pstate/Makefile @@ -4,6 +4,15 @@ # No binaries, but make sure arg-less "make" doesn't trigger "run_tests" all: -TEST_PROGS := amd-pstate-ut.sh +uname_M := $(shell uname -m 2>/dev/null || echo not) +ARCH ?= $(shell echo $(uname_M) | sed -e s/i.86/x86/ -e s/x86_64/x86/) + +ifeq (x86,$(ARCH)) +TEST_GEN_FILES += ../../../power/x86/amd_pstate_tracer/amd_pstate_trace.py +TEST_GEN_FILES += ../../../power/x86/intel_pstate_tracer/intel_pstate_tracer.py +endif + +TEST_PROGS := run.sh +TEST_FILES := basic.sh tbench.sh gitsource.sh include ../lib.mk diff --git a/tools/testing/selftests/amd-pstate/amd-pstate-ut.sh b/tools/testing/selftests/amd-pstate/amd-pstate-ut.sh deleted file mode 100755 index f8e82d91ffcf..000000000000 --- a/tools/testing/selftests/amd-pstate/amd-pstate-ut.sh +++ /dev/null @@ -1,56 +0,0 @@ -#!/bin/sh -# SPDX-License-Identifier: GPL-2.0 - -# amd-pstate-ut is a test module for testing the amd-pstate driver. -# It can only run on x86 architectures and current cpufreq driver -# must be amd-pstate. -# (1) It can help all users to verify their processor support -# (SBIOS/Firmware or Hardware). -# (2) Kernel can have a basic function test to avoid the kernel -# regression during the update. -# (3) We can introduce more functional or performance tests to align -# the result together, it will benefit power and performance scale optimization. - -# Kselftest framework requirement - SKIP code is 4. -ksft_skip=4 - -# 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/') -VENDOR=$(cat /proc/cpuinfo | grep -m 1 'vendor_id' | awk '{print $NF}') - -if ! echo "$ARCH" | grep -q x86; then - echo "$0 # Skipped: Test can only run on x86 architectures." - exit $ksft_skip -fi - -if ! echo "$VENDOR" | grep -iq amd; then - echo "$0 # Skipped: Test can only run on AMD CPU." - echo "$0 # Current cpu vendor is $VENDOR." - exit $ksft_skip -fi - -scaling_driver=$(cat /sys/devices/system/cpu/cpufreq/policy0/scaling_driver) -if [ "$scaling_driver" != "amd-pstate" ]; then - echo "$0 # Skipped: Test can only run on amd-pstate driver." - echo "$0 # Please set X86_AMD_PSTATE enabled." - echo "$0 # Current cpufreq scaling drvier is $scaling_driver." - exit $ksft_skip -fi - -msg="Skip all tests:" -if [ ! -w /dev ]; then - echo $msg please run this as root >&2 - exit $ksft_skip -fi - -if ! /sbin/modprobe -q -n amd-pstate-ut; then - echo "amd-pstate-ut: module amd-pstate-ut is not found [SKIP]" - exit $ksft_skip -fi -if /sbin/modprobe -q amd-pstate-ut; then - /sbin/modprobe -q -r amd-pstate-ut - echo "amd-pstate-ut: ok" -else - echo "amd-pstate-ut: [FAIL]" - exit 1 -fi diff --git a/tools/testing/selftests/amd-pstate/basic.sh b/tools/testing/selftests/amd-pstate/basic.sh new file mode 100755 index 000000000000..e4c43193e4a3 --- /dev/null +++ b/tools/testing/selftests/amd-pstate/basic.sh @@ -0,0 +1,38 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 + +# amd-pstate-ut is a test module for testing the amd-pstate driver. +# It can only run on x86 architectures and current cpufreq driver +# must be amd-pstate. +# (1) It can help all users to verify their processor support +# (SBIOS/Firmware or Hardware). +# (2) Kernel can have a basic function test to avoid the kernel +# regression during the update. +# (3) We can introduce more functional or performance tests to align +# the result together, it will benefit power and performance scale optimization. + +# protect against multiple inclusion +if [ $FILE_BASIC ]; then + return 0 +else + FILE_BASIC=DONE +fi + +amd_pstate_basic() +{ + printf "\n---------------------------------------------\n" + printf "*** Running AMD P-state ut ***" + printf "\n---------------------------------------------\n" + + if ! /sbin/modprobe -q -n amd-pstate-ut; then + echo "amd-pstate-ut: module amd-pstate-ut is not found [SKIP]" + exit $ksft_skip + fi + if /sbin/modprobe -q amd-pstate-ut; then + /sbin/modprobe -q -r amd-pstate-ut + echo "amd-pstate-basic: ok" + else + echo "amd-pstate-basic: [FAIL]" + exit 1 + fi +} diff --git a/tools/testing/selftests/amd-pstate/gitsource.sh b/tools/testing/selftests/amd-pstate/gitsource.sh new file mode 100755 index 000000000000..dbc1fe45599d --- /dev/null +++ b/tools/testing/selftests/amd-pstate/gitsource.sh @@ -0,0 +1,354 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 + +# Testing and monitor the cpu desire performance, frequency, load, +# power consumption and throughput etc. when this script trigger +# gitsource test. +# 1) Download and tar gitsource codes. +# 2) Run gitsource benchmark on specific governors, ondemand or schedutil. +# 3) Run tbench benchmark comparative test on acpi-cpufreq kernel driver. +# 4) Get desire performance, frequency, load by perf. +# 5) Get power consumption and throughput by amd_pstate_trace.py. +# 6) Get run time by /usr/bin/time. +# 7) Analyse test results and save it in file selftest.gitsource.csv. +#8) Plot png images about time, energy and performance per watt for each test. + +# protect against multiple inclusion +if [ $FILE_GITSOURCE ]; then + return 0 +else + FILE_GITSOURCE=DONE +fi + +git_name="git-2.15.1" +git_tar="$git_name.tar.gz" +gitsource_url="https://github.com/git/git/archive/refs/tags/v2.15.1.tar.gz" +gitsource_governors=("ondemand" "schedutil") + +# $1: governor, $2: round, $3: des-perf, $4: freq, $5: load, $6: time $7: energy, $8: PPW +store_csv_gitsource() +{ + echo "$1, $2, $3, $4, $5, $6, $7, $8" | tee -a $OUTFILE_GIT.csv > /dev/null 2>&1 +} + +# clear some special lines +clear_csv_gitsource() +{ + if [ -f $OUTFILE_GIT.csv ]; then + sed -i '/Comprison(%)/d' $OUTFILE_GIT.csv + sed -i "/$(scaling_name)/d" $OUTFILE_GIT.csv + fi +} + +# find string $1 in file csv and get the number of lines +get_lines_csv_gitsource() +{ + if [ -f $OUTFILE_GIT.csv ]; then + return `grep -c "$1" $OUTFILE_GIT.csv` + else + return 0 + fi +} + +pre_clear_gitsource() +{ + post_clear_gitsource + rm -rf gitsource_*.png + clear_csv_gitsource +} + +post_clear_gitsource() +{ + rm -rf results/tracer-gitsource* + rm -rf $OUTFILE_GIT*.log + rm -rf $OUTFILE_GIT*.result +} + +install_gitsource() +{ + if [ ! -d $git_name ]; then + 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 + fi +} + +# $1: governor, $2: loop +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 & + + 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 .. + + for job in `jobs -p` + do + echo "Waiting for job id $job" + wait $job + done +} + +# $1: governor, $2: loop +parse_gitsource() +{ + awk '{print $5}' results/tracer-gitsource-$1-$2/cpu.csv | sed -e '1d' | sed s/,// > $OUTFILE_GIT-des-perf-$1-$2.log + avg_des_perf=$(awk 'BEGIN {i=0; sum=0};{i++; sum += $1};END {print sum/i}' $OUTFILE_GIT-des-perf-$1-$2.log) + printf "Gitsource-$1-#$2 avg des perf: $avg_des_perf\n" | tee -a $OUTFILE_GIT.result + + awk '{print $7}' results/tracer-gitsource-$1-$2/cpu.csv | sed -e '1d' | sed s/,// > $OUTFILE_GIT-freq-$1-$2.log + avg_freq=$(awk 'BEGIN {i=0; sum=0};{i++; sum += $1};END {print sum/i}' $OUTFILE_GIT-freq-$1-$2.log) + printf "Gitsource-$1-#$2 avg freq: $avg_freq\n" | tee -a $OUTFILE_GIT.result + + awk '{print $11}' results/tracer-gitsource-$1-$2/cpu.csv | sed -e '1d' | sed s/,// > $OUTFILE_GIT-load-$1-$2.log + avg_load=$(awk 'BEGIN {i=0; sum=0};{i++; sum += $1};END {print sum/i}' $OUTFILE_GIT-load-$1-$2.log) + printf "Gitsource-$1-#$2 avg load: $avg_load\n" | tee -a $OUTFILE_GIT.result + + grep user $OUTFILE_GIT.time-gitsource-$1-$2.log | awk '{print $1}' | sed -e 's/user//' > $OUTFILE_GIT-time-$1-$2.log + time_sum=$(awk 'BEGIN {sum=0};{sum += $1};END {print sum}' $OUTFILE_GIT-time-$1-$2.log) + printf "Gitsource-$1-#$2 user time(s): $time_sum\n" | tee -a $OUTFILE_GIT.result + + grep Joules $OUTFILE_GIT-perf-$1-$2.log | awk '{print $4}' > $OUTFILE_GIT-energy-$1-$2.log + en_sum=$(awk 'BEGIN {sum=0};{sum += $1};END {print sum}' $OUTFILE_GIT-energy-$1-$2.log) + printf "Gitsource-$1-#$2 power consumption(J): $en_sum\n" | tee -a $OUTFILE_GIT.result + + # Permance is the number of run gitsource per second, denoted 1/t, where 1 is the number of run gitsource in t + # senconds. It is well known that P=E/t, where P is power measured in watts(W), E is energy measured in joules(J), + # and t is time measured in seconds(s). This means that performance per watt becomes + # 1/t 1/t 1 + # ----- = ----- = --- + # P E/t E + # with unit given by 1 per joule. + ppw=`echo "scale=9;1/$en_sum" | bc | awk '{printf "%.9f", $0}'` + printf "Gitsource-$1-#$2 performance per watt(1/J): $ppw\n" | tee -a $OUTFILE_GIT.result + printf "\n" | tee -a $OUTFILE_GIT.result + + driver_name=`echo $(scaling_name)` + store_csv_gitsource "$driver_name-$1" $2 $avg_des_perf $avg_freq $avg_load $time_sum $en_sum $ppw +} + +# $1: governor +loop_gitsource() +{ + printf "\nGitsource total test times is $LOOP_TIMES for $1\n\n" + for i in `seq 1 $LOOP_TIMES` + do + run_gitsource $1 $i + parse_gitsource $1 $i + done +} + +# $1: governor +gather_gitsource() +{ + printf "Gitsource test result for $1 (loops:$LOOP_TIMES)" | tee -a $OUTFILE_GIT.result + printf "\n--------------------------------------------------\n" | tee -a $OUTFILE_GIT.result + + grep "Gitsource-$1-#" $OUTFILE_GIT.result | grep "avg des perf:" | awk '{print $NF}' > $OUTFILE_GIT-des-perf-$1.log + avg_des_perf=$(awk 'BEGIN {sum=0};{sum += $1};END {print sum/'$LOOP_TIMES'}' $OUTFILE_GIT-des-perf-$1.log) + printf "Gitsource-$1 avg des perf: $avg_des_perf\n" | tee -a $OUTFILE_GIT.result + + grep "Gitsource-$1-#" $OUTFILE_GIT.result | grep "avg freq:" | awk '{print $NF}' > $OUTFILE_GIT-freq-$1.log + avg_freq=$(awk 'BEGIN {sum=0};{sum += $1};END {print sum/'$LOOP_TIMES'}' $OUTFILE_GIT-freq-$1.log) + printf "Gitsource-$1 avg freq: $avg_freq\n" | tee -a $OUTFILE_GIT.result + + grep "Gitsource-$1-#" $OUTFILE_GIT.result | grep "avg load:" | awk '{print $NF}' > $OUTFILE_GIT-load-$1.log + avg_load=$(awk 'BEGIN {sum=0};{sum += $1};END {print sum/'$LOOP_TIMES'}' $OUTFILE_GIT-load-$1.log) + printf "Gitsource-$1 avg load: $avg_load\n" | tee -a $OUTFILE_GIT.result + + grep "Gitsource-$1-#" $OUTFILE_GIT.result | grep "user time(s):" | awk '{print $NF}' > $OUTFILE_GIT-time-$1.log + time_sum=$(awk 'BEGIN {sum=0};{sum += $1};END {print sum}' $OUTFILE_GIT-time-$1.log) + printf "Gitsource-$1 total user time(s): $time_sum\n" | tee -a $OUTFILE_GIT.result + + avg_time=$(awk 'BEGIN {sum=0};{sum += $1};END {print sum/'$LOOP_TIMES'}' $OUTFILE_GIT-time-$1.log) + printf "Gitsource-$1 avg user times(s): $avg_time\n" | tee -a $OUTFILE_GIT.result + + grep "Gitsource-$1-#" $OUTFILE_GIT.result | grep "power consumption(J):" | awk '{print $NF}' > $OUTFILE_GIT-energy-$1.log + en_sum=$(awk 'BEGIN {sum=0};{sum += $1};END {print sum}' $OUTFILE_GIT-energy-$1.log) + printf "Gitsource-$1 total power consumption(J): $en_sum\n" | tee -a $OUTFILE_GIT.result + + avg_en=$(awk 'BEGIN {sum=0};{sum += $1};END {print sum/'$LOOP_TIMES'}' $OUTFILE_GIT-energy-$1.log) + printf "Gitsource-$1 avg power consumption(J): $avg_en\n" | tee -a $OUTFILE_GIT.result + + # Permance is the number of run gitsource per second, denoted 1/t, where 1 is the number of run gitsource in t + # senconds. It is well known that P=E/t, where P is power measured in watts(W), E is energy measured in joules(J), + # and t is time measured in seconds(s). This means that performance per watt becomes + # 1/t 1/t 1 + # ----- = ----- = --- + # P E/t E + # with unit given by 1 per joule. + ppw=`echo "scale=9;1/$avg_en" | bc | awk '{printf "%.9f", $0}'` + printf "Gitsource-$1 performance per watt(1/J): $ppw\n" | tee -a $OUTFILE_GIT.result + printf "\n" | tee -a $OUTFILE_GIT.result + + driver_name=`echo $(scaling_name)` + store_csv_gitsource "$driver_name-$1" "Average" $avg_des_perf $avg_freq $avg_load $avg_time $avg_en $ppw +} + +# $1: base scaling_driver $2: base governor $3: comparison scaling_driver $4: comparison governor +__calc_comp_gitsource() +{ + base=`grep "$1-$2" $OUTFILE_GIT.csv | grep "Average"` + comp=`grep "$3-$4" $OUTFILE_GIT.csv | grep "Average"` + + if [ -n "$base" -a -n "$comp" ]; then + printf "\n==================================================\n" | tee -a $OUTFILE_GIT.result + printf "Gitsource comparison $1-$2 VS $3-$4" | tee -a $OUTFILE_GIT.result + printf "\n==================================================\n" | tee -a $OUTFILE_GIT.result + + # get the base values + des_perf_base=`echo "$base" | awk '{print $3}' | sed s/,//` + freq_base=`echo "$base" | awk '{print $4}' | sed s/,//` + load_base=`echo "$base" | awk '{print $5}' | sed s/,//` + time_base=`echo "$base" | awk '{print $6}' | sed s/,//` + energy_base=`echo "$base" | awk '{print $7}' | sed s/,//` + ppw_base=`echo "$base" | awk '{print $8}' | sed s/,//` + + # get the comparison values + des_perf_comp=`echo "$comp" | awk '{print $3}' | sed s/,//` + freq_comp=`echo "$comp" | awk '{print $4}' | sed s/,//` + load_comp=`echo "$comp" | awk '{print $5}' | sed s/,//` + time_comp=`echo "$comp" | awk '{print $6}' | sed s/,//` + energy_comp=`echo "$comp" | awk '{print $7}' | sed s/,//` + ppw_comp=`echo "$comp" | awk '{print $8}' | sed s/,//` + + # compare the base and comp values + des_perf_drop=`echo "scale=4;($des_perf_comp-$des_perf_base)*100/$des_perf_base" | bc | awk '{printf "%.4f", $0}'` + printf "Gitsource-$1 des perf base: $des_perf_base comprison: $des_perf_comp percent: $des_perf_drop\n" | tee -a $OUTFILE_GIT.result + + freq_drop=`echo "scale=4;($freq_comp-$freq_base)*100/$freq_base" | bc | awk '{printf "%.4f", $0}'` + printf "Gitsource-$1 freq base: $freq_base comprison: $freq_comp percent: $freq_drop\n" | tee -a $OUTFILE_GIT.result + + load_drop=`echo "scale=4;($load_comp-$load_base)*100/$load_base" | bc | awk '{printf "%.4f", $0}'` + printf "Gitsource-$1 load base: $load_base comprison: $load_comp percent: $load_drop\n" | tee -a $OUTFILE_GIT.result + + time_drop=`echo "scale=4;($time_comp-$time_base)*100/$time_base" | bc | awk '{printf "%.4f", $0}'` + printf "Gitsource-$1 time base: $time_base comprison: $time_comp percent: $time_drop\n" | tee -a $OUTFILE_GIT.result + + energy_drop=`echo "scale=4;($energy_comp-$energy_base)*100/$energy_base" | bc | awk '{printf "%.4f", $0}'` + printf "Gitsource-$1 energy base: $energy_base comprison: $energy_comp percent: $energy_drop\n" | tee -a $OUTFILE_GIT.result + + ppw_drop=`echo "scale=4;($ppw_comp-$ppw_base)*100/$ppw_base" | bc | awk '{printf "%.4f", $0}'` + printf "Gitsource-$1 performance per watt base: $ppw_base comprison: $ppw_comp percent: $ppw_drop\n" | tee -a $OUTFILE_GIT.result + printf "\n" | tee -a $OUTFILE_GIT.result + + store_csv_gitsource "$1-$2 VS $3-$4" "Comprison(%)" "$des_perf_drop" "$freq_drop" "$load_drop" "$time_drop" "$energy_drop" "$ppw_drop" + fi +} + +# calculate the comparison(%) +calc_comp_gitsource() +{ + # acpi-cpufreq-ondemand VS acpi-cpufreq-schedutil + __calc_comp_gitsource ${all_scaling_names[0]} ${gitsource_governors[0]} ${all_scaling_names[0]} ${gitsource_governors[1]} + + # amd-pstate-ondemand VS amd-pstate-schedutil + __calc_comp_gitsource ${all_scaling_names[1]} ${gitsource_governors[0]} ${all_scaling_names[1]} ${gitsource_governors[1]} + + # acpi-cpufreq-ondemand VS amd-pstate-ondemand + __calc_comp_gitsource ${all_scaling_names[0]} ${gitsource_governors[0]} ${all_scaling_names[1]} ${gitsource_governors[0]} + + # acpi-cpufreq-schedutil VS amd-pstate-schedutil + __calc_comp_gitsource ${all_scaling_names[0]} ${gitsource_governors[1]} ${all_scaling_names[1]} ${gitsource_governors[1]} +} + +# $1: file_name, $2: title, $3: ylable, $4: column +plot_png_gitsource() +{ + # all_scaling_names[1] all_scaling_names[0] flag + # amd-pstate acpi-cpufreq + # N N 0 + # N Y 1 + # Y N 2 + # Y Y 3 + ret=`grep -c "${all_scaling_names[1]}" $OUTFILE_GIT.csv` + if [ $ret -eq 0 ]; then + ret=`grep -c "${all_scaling_names[0]}" $OUTFILE_GIT.csv` + if [ $ret -eq 0 ]; then + flag=0 + else + flag=1 + fi + else + ret=`grep -c "${all_scaling_names[0]}" $OUTFILE_GIT.csv` + if [ $ret -eq 0 ]; then + flag=2 + else + flag=3 + fi + fi + + gnuplot << EOF + set term png + set output "$1" + + set title "$2" + set xlabel "Test Cycles (round)" + set ylabel "$3" + + set grid + set style data histogram + set style fill solid 0.5 border + set boxwidth 0.8 + + if ($flag == 1) { + plot \ + "<(sed -n -e 's/,//g' -e '/${all_scaling_names[0]}-${gitsource_governors[0]}/p' $OUTFILE_GIT.csv)" using $4:xtic(2) title "${all_scaling_names[0]}-${gitsource_governors[0]}", \ + "<(sed -n -e 's/,//g' -e '/${all_scaling_names[0]}-${gitsource_governors[1]}/p' $OUTFILE_GIT.csv)" using $4:xtic(2) title "${all_scaling_names[0]}-${gitsource_governors[1]}" + } else { + if ($flag == 2) { + plot \ + "<(sed -n -e 's/,//g' -e '/${all_scaling_names[1]}-${gitsource_governors[0]}/p' $OUTFILE_GIT.csv)" using $4:xtic(2) title "${all_scaling_names[1]}-${gitsource_governors[0]}", \ + "<(sed -n -e 's/,//g' -e '/${all_scaling_names[1]}-${gitsource_governors[1]}/p' $OUTFILE_GIT.csv)" using $4:xtic(2) title "${all_scaling_names[1]}-${gitsource_governors[1]}" + } else { + if ($flag == 3 ) { + plot \ + "<(sed -n -e 's/,//g' -e '/${all_scaling_names[0]}-${gitsource_governors[0]}/p' $OUTFILE_GIT.csv)" using $4:xtic(2) title "${all_scaling_names[0]}-${gitsource_governors[0]}", \ + "<(sed -n -e 's/,//g' -e '/${all_scaling_names[0]}-${gitsource_governors[1]}/p' $OUTFILE_GIT.csv)" using $4:xtic(2) title "${all_scaling_names[0]}-${gitsource_governors[1]}", \ + "<(sed -n -e 's/,//g' -e '/${all_scaling_names[1]}-${gitsource_governors[0]}/p' $OUTFILE_GIT.csv)" using $4:xtic(2) title "${all_scaling_names[1]}-${gitsource_governors[0]}", \ + "<(sed -n -e 's/,//g' -e '/${all_scaling_names[1]}-${gitsource_governors[1]}/p' $OUTFILE_GIT.csv)" using $4:xtic(2) title "${all_scaling_names[1]}-${gitsource_governors[1]}" + } + } + } + quit +EOF +} + +amd_pstate_gitsource() +{ + printf "\n---------------------------------------------\n" + printf "*** Running gitsource ***" + printf "\n---------------------------------------------\n" + + pre_clear_gitsource + + install_gitsource + + get_lines_csv_gitsource "Governor" + if [ $? -eq 0 ]; then + # add titles and unit for csv file + store_csv_gitsource "Governor" "Round" "Des-perf" "Freq" "Load" "Time" "Energy" "Performance Per Watt" + store_csv_gitsource "Unit" "" "" "GHz" "" "s" "J" "1/J" + fi + + backup_governor + for governor in ${gitsource_governors[*]} ; do + printf "\nSpecified governor is $governor\n\n" + switch_governor $governor + loop_gitsource $governor + gather_gitsource $governor + done + restore_governor + + plot_png_gitsource "gitsource_time.png" "Gitsource Benchmark Time" "Time (s)" 6 + plot_png_gitsource "gitsource_energy.png" "Gitsource Benchmark Energy" "Energy (J)" 7 + plot_png_gitsource "gitsource_ppw.png" "Gitsource Benchmark Performance Per Watt" "Performance Per Watt (1/J)" 8 + + calc_comp_gitsource + + post_clear_gitsource +} diff --git a/tools/testing/selftests/amd-pstate/run.sh b/tools/testing/selftests/amd-pstate/run.sh new file mode 100755 index 000000000000..57cad57e59c0 --- /dev/null +++ b/tools/testing/selftests/amd-pstate/run.sh @@ -0,0 +1,387 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-2.0 + +# protect against multiple inclusion +if [ $FILE_MAIN ]; then + return 0 +else + FILE_MAIN=DONE +fi + +source basic.sh +source tbench.sh +source 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/') +VENDOR=$(cat /proc/cpuinfo | grep -m 1 'vendor_id' | awk '{print $NF}') + +msg="Skip all tests:" +FUNC=all +OUTFILE=selftest +OUTFILE_TBENCH="$OUTFILE.tbench" +OUTFILE_GIT="$OUTFILE.gitsource" + +SYSFS= +CPUROOT= +CPUFREQROOT= +MAKE_CPUS= + +TIME_LIMIT=100 +PROCESS_NUM=128 +LOOP_TIMES=3 +TRACER_INTERVAL=10 +CURRENT_TEST=amd-pstate +COMPARATIVE_TEST= + +# Kselftest framework requirement - SKIP code is 4. +ksft_skip=4 +all_scaling_names=("acpi-cpufreq" "amd-pstate") + +# Get current cpufreq scaling driver name +scaling_name() +{ + if [ "$COMPARATIVE_TEST" = "" ]; then + echo "$CURRENT_TEST" + else + echo "$COMPARATIVE_TEST" + fi +} + +# Counts CPUs with cpufreq directories +count_cpus() +{ + count=0; + + for cpu in `ls $CPUROOT | grep "cpu[0-9].*"`; do + if [ -d $CPUROOT/$cpu/cpufreq ]; then + let count=count+1; + fi + done + + echo $count; +} + +# $1: policy +find_current_governor() +{ + cat $CPUFREQROOT/$1/scaling_governor +} + +backup_governor() +{ + policies=$(ls $CPUFREQROOT| grep "policy[0-9].*") + for policy in $policies; do + cur_gov=$(find_current_governor $policy) + echo "$policy $cur_gov" >> $OUTFILE.backup_governor.log + done + + printf "Governor $cur_gov backup done.\n" +} + +restore_governor() +{ + i=0; + + policies=$(awk '{print $1}' $OUTFILE.backup_governor.log) + for policy in $policies; do + let i++; + governor=$(sed -n ''$i'p' $OUTFILE.backup_governor.log | awk '{print $2}') + + # switch governor + echo $governor > $CPUFREQROOT/$policy/scaling_governor + done + + printf "Governor restored to $governor.\n" +} + +# $1: governor +switch_governor() +{ + policies=$(ls $CPUFREQROOT| grep "policy[0-9].*") + for policy in $policies; do + filepath=$CPUFREQROOT/$policy/scaling_available_governors + + # Exit if cpu isn't managed by cpufreq core + if [ ! -f $filepath ]; then + return; + fi + + echo $1 > $CPUFREQROOT/$policy/scaling_governor + done + + printf "Switched governor to $1.\n" +} + +# All amd-pstate tests +amd_pstate_all() +{ + printf "\n=============================================\n" + printf "***** Running AMD P-state Sanity Tests *****\n" + printf "=============================================\n\n" + + count=$(count_cpus) + if [ $count = 0 ]; then + printf "No cpu is managed by cpufreq core, exiting\n" + exit; + else + printf "AMD P-state manages: $count CPUs\n" + fi + + # unit test for amd-pstate kernel driver + amd_pstate_basic + + # tbench + amd_pstate_tbench + + # gitsource + amd_pstate_gitsource +} + +help() +{ + printf "Usage: $0 [OPTION...] + [-h <help>] + [-o <output-file-for-dump>] + [-c <all: All testing, + basic: Basic testing, + tbench: Tbench testing, + gitsource: Gitsource testing.>] + [-t <tbench time limit>] + [-p <tbench process number>] + [-l <loop times for tbench>] + [-i <amd tracer interval>] + [-m <comparative test: acpi-cpufreq>] + \n" + exit 2 +} + +parse_arguments() +{ + while getopts ho:c:t:p:l:i:m: arg + do + case $arg in + h) # --help + help + ;; + + c) # --func_type (Function to perform: basic, tbench, gitsource (default: all)) + FUNC=$OPTARG + ;; + + o) # --output-file (Output file to store dumps) + OUTFILE=$OPTARG + ;; + + t) # --tbench-time-limit + TIME_LIMIT=$OPTARG + ;; + + p) # --tbench-process-number + PROCESS_NUM=$OPTARG + ;; + + l) # --tbench/gitsource-loop-times + LOOP_TIMES=$OPTARG + ;; + + i) # --amd-tracer-interval + TRACER_INTERVAL=$OPTARG + ;; + + m) # --comparative-test + COMPARATIVE_TEST=$OPTARG + ;; + + *) + help + ;; + esac + done +} + +command_perf() +{ + if ! command -v perf > /dev/null; then + echo $msg please install perf. >&2 + exit $ksft_skip + fi +} + +command_tbench() +{ + if ! command -v tbench > /dev/null; then + if apt policy dbench > /dev/null 2>&1; then + echo $msg apt install dbench >&2 + exit $ksft_skip + elif yum list available | grep dbench > /dev/null 2>&1; then + echo $msg yum install dbench >&2 + exit $ksft_skip + fi + fi + + if ! command -v tbench > /dev/null; then + echo $msg please install tbench. >&2 + exit $ksft_skip + fi +} + +prerequisite() +{ + if ! echo "$ARCH" | grep -q x86; then + echo "$0 # Skipped: Test can only run on x86 architectures." + exit $ksft_skip + fi + + if ! echo "$VENDOR" | grep -iq amd; then + echo "$0 # Skipped: Test can only run on AMD CPU." + echo "$0 # Current cpu vendor is $VENDOR." + exit $ksft_skip + fi + + scaling_driver=$(cat /sys/devices/system/cpu/cpufreq/policy0/scaling_driver) + if [ "$COMPARATIVE_TEST" = "" ]; then + if [ "$scaling_driver" != "$CURRENT_TEST" ]; then + echo "$0 # Skipped: Test can only run on $CURRENT_TEST driver or run comparative test." + echo "$0 # Please set X86_AMD_PSTATE enabled or run comparative test." + echo "$0 # Current cpufreq scaling drvier is $scaling_driver." + exit $ksft_skip + fi + else + case "$FUNC" in + "tbench" | "gitsource") + if [ "$scaling_driver" != "$COMPARATIVE_TEST" ]; then + echo "$0 # Skipped: Comparison test can only run on $COMPARISON_TEST driver." + echo "$0 # Current cpufreq scaling drvier is $scaling_driver." + exit $ksft_skip + fi + ;; + + *) + echo "$0 # Skipped: Comparison test are only for tbench or gitsource." + echo "$0 # Current comparative test is for $FUNC." + exit $ksft_skip + ;; + esac + fi + + if [ ! -w /dev ]; then + echo $msg please run this as root >&2 + exit $ksft_skip + fi + + case "$FUNC" in + "all") + command_perf + command_tbench + ;; + + "tbench") + command_perf + command_tbench + ;; + + "gitsource") + command_perf + ;; + esac + + SYSFS=`mount -t sysfs | head -1 | awk '{ print $3 }'` + + if [ ! -d "$SYSFS" ]; then + echo $msg sysfs is not mounted >&2 + exit 2 + fi + + CPUROOT=$SYSFS/devices/system/cpu + CPUFREQROOT="$CPUROOT/cpufreq" + + if ! ls $CPUROOT/cpu* > /dev/null 2>&1; then + echo $msg cpus not available in sysfs >&2 + exit 2 + fi + + if ! ls $CPUROOT/cpufreq > /dev/null 2>&1; then + echo $msg cpufreq directory not available in sysfs >&2 + exit 2 + fi +} + +do_test() +{ + # Check if CPUs are managed by cpufreq or not + count=$(count_cpus) + MAKE_CPUS=$((count*2)) + + if [ $count = 0 ]; then + echo "No cpu is managed by cpufreq core, exiting" + exit 2; + fi + + case "$FUNC" in + "all") + amd_pstate_all + ;; + + "basic") + amd_pstate_basic + ;; + + "tbench") + amd_pstate_tbench + ;; + + "gitsource") + amd_pstate_gitsource + ;; + + *) + echo "Invalid [-f] function type" + help + ;; + esac +} + +# clear dumps +pre_clear_dumps() +{ + case "$FUNC" in + "all") + rm -rf $OUTFILE.log + rm -rf $OUTFILE.backup_governor.log + rm -rf *.png + ;; + + "tbench") + rm -rf $OUTFILE.log + rm -rf $OUTFILE.backup_governor.log + rm -rf tbench_*.png + ;; + + "gitsource") + rm -rf $OUTFILE.log + rm -rf $OUTFILE.backup_governor.log + rm -rf gitsource_*.png + ;; + + *) + ;; + esac +} + +post_clear_dumps() +{ + rm -rf $OUTFILE.log + rm -rf $OUTFILE.backup_governor.log +} + +# Parse arguments +parse_arguments $@ + +# Make sure all requirements are met +prerequisite + +# Run requested functions +pre_clear_dumps +do_test | tee -a $OUTFILE.log +post_clear_dumps diff --git a/tools/testing/selftests/amd-pstate/tbench.sh b/tools/testing/selftests/amd-pstate/tbench.sh new file mode 100755 index 000000000000..49c9850341f6 --- /dev/null +++ b/tools/testing/selftests/amd-pstate/tbench.sh @@ -0,0 +1,339 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 + +# Testing and monitor the cpu desire performance, frequency, load, +# power consumption and throughput etc.when this script trigger tbench +# test cases. +# 1) Run tbench benchmark on specific governors, ondemand or schedutil. +# 2) Run tbench benchmark comparative test on acpi-cpufreq kernel driver. +# 3) Get desire performance, frequency, load by perf. +# 4) Get power consumption and throughput by amd_pstate_trace.py. +# 5) Analyse test results and save it in file selftest.tbench.csv. +# 6) Plot png images about performance, energy and performance per watt for each test. + +# protect against multiple inclusion +if [ $FILE_TBENCH ]; then + return 0 +else + FILE_TBENCH=DONE +fi + +tbench_governors=("ondemand" "schedutil") + +# $1: governor, $2: round, $3: des-perf, $4: freq, $5: load, $6: performance, $7: energy, $8: performance per watt +store_csv_tbench() +{ + echo "$1, $2, $3, $4, $5, $6, $7, $8" | tee -a $OUTFILE_TBENCH.csv > /dev/null 2>&1 +} + +# clear some special lines +clear_csv_tbench() +{ + if [ -f $OUTFILE_TBENCH.csv ]; then + sed -i '/Comprison(%)/d' $OUTFILE_TBENCH.csv + sed -i "/$(scaling_name)/d" $OUTFILE_TBENCH.csv + fi +} + +# find string $1 in file csv and get the number of lines +get_lines_csv_tbench() +{ + if [ -f $OUTFILE_TBENCH.csv ]; then + return `grep -c "$1" $OUTFILE_TBENCH.csv` + else + return 0 + fi +} + +pre_clear_tbench() +{ + post_clear_tbench + rm -rf tbench_*.png + clear_csv_tbench +} + +post_clear_tbench() +{ + rm -rf results/tracer-tbench* + rm -rf $OUTFILE_TBENCH*.log + rm -rf $OUTFILE_TBENCH*.result + +} + +# $1: governor, $2: loop +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 & + + 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 + + pid=`pidof tbench_srv` + kill $pid + + for job in `jobs -p` + do + echo "Waiting for job id $job" + wait $job + done +} + +# $1: governor, $2: loop +parse_tbench() +{ + awk '{print $5}' results/tracer-tbench-$1-$2/cpu.csv | sed -e '1d' | sed s/,// > $OUTFILE_TBENCH-des-perf-$1-$2.log + avg_des_perf=$(awk 'BEGIN {i=0; sum=0};{i++; sum += $1};END {print sum/i}' $OUTFILE_TBENCH-des-perf-$1-$2.log) + printf "Tbench-$1-#$2 avg des perf: $avg_des_perf\n" | tee -a $OUTFILE_TBENCH.result + + awk '{print $7}' results/tracer-tbench-$1-$2/cpu.csv | sed -e '1d' | sed s/,// > $OUTFILE_TBENCH-freq-$1-$2.log + avg_freq=$(awk 'BEGIN {i=0; sum=0};{i++; sum += $1};END {print sum/i}' $OUTFILE_TBENCH-freq-$1-$2.log) + printf "Tbench-$1-#$2 avg freq: $avg_freq\n" | tee -a $OUTFILE_TBENCH.result + + awk '{print $11}' results/tracer-tbench-$1-$2/cpu.csv | sed -e '1d' | sed s/,// > $OUTFILE_TBENCH-load-$1-$2.log + avg_load=$(awk 'BEGIN {i=0; sum=0};{i++; sum += $1};END {print sum/i}' $OUTFILE_TBENCH-load-$1-$2.log) + printf "Tbench-$1-#$2 avg load: $avg_load\n" | tee -a $OUTFILE_TBENCH.result + + grep Throughput $OUTFILE_TBENCH-perf-$1-$2.log | awk '{print $2}' > $OUTFILE_TBENCH-throughput-$1-$2.log + tp_sum=$(awk 'BEGIN {sum=0};{sum += $1};END {print sum}' $OUTFILE_TBENCH-throughput-$1-$2.log) + printf "Tbench-$1-#$2 throughput(MB/s): $tp_sum\n" | tee -a $OUTFILE_TBENCH.result + + grep Joules $OUTFILE_TBENCH-perf-$1-$2.log | awk '{print $4}' > $OUTFILE_TBENCH-energy-$1-$2.log + en_sum=$(awk 'BEGIN {sum=0};{sum += $1};END {print sum}' $OUTFILE_TBENCH-energy-$1-$2.log) + printf "Tbench-$1-#$2 power consumption(J): $en_sum\n" | tee -a $OUTFILE_TBENCH.result + + # Permance is throughput per second, denoted T/t, where T is throught rendered in t seconds. + # It is well known that P=E/t, where P is power measured in watts(W), E is energy measured in joules(J), + # and t is time measured in seconds(s). This means that performance per watt becomes + # T/t T/t T + # --- = --- = --- + # P E/t E + # with unit given by MB per joule. + ppw=`echo "scale=4;($TIME_LIMIT-1)*$tp_sum/$en_sum" | bc | awk '{printf "%.4f", $0}'` + printf "Tbench-$1-#$2 performance per watt(MB/J): $ppw\n" | tee -a $OUTFILE_TBENCH.result + printf "\n" | tee -a $OUTFILE_TBENCH.result + + driver_name=`echo $(scaling_name)` + store_csv_tbench "$driver_name-$1" $2 $avg_des_perf $avg_freq $avg_load $tp_sum $en_sum $ppw +} + +# $1: governor +loop_tbench() +{ + printf "\nTbench total test times is $LOOP_TIMES for $1\n\n" + for i in `seq 1 $LOOP_TIMES` + do + run_tbench $1 $i + parse_tbench $1 $i + done +} + +# $1: governor +gather_tbench() +{ + printf "Tbench test result for $1 (loops:$LOOP_TIMES)" | tee -a $OUTFILE_TBENCH.result + printf "\n--------------------------------------------------\n" | tee -a $OUTFILE_TBENCH.result + + grep "Tbench-$1-#" $OUTFILE_TBENCH.result | grep "avg des perf:" | awk '{print $NF}' > $OUTFILE_TBENCH-des-perf-$1.log + avg_des_perf=$(awk 'BEGIN {sum=0};{sum += $1};END {print sum/'$LOOP_TIMES'}' $OUTFILE_TBENCH-des-perf-$1.log) + printf "Tbench-$1 avg des perf: $avg_des_perf\n" | tee -a $OUTFILE_TBENCH.result + + grep "Tbench-$1-#" $OUTFILE_TBENCH.result | grep "avg freq:" | awk '{print $NF}' > $OUTFILE_TBENCH-freq-$1.log + avg_freq=$(awk 'BEGIN {sum=0};{sum += $1};END {print sum/'$LOOP_TIMES'}' $OUTFILE_TBENCH-freq-$1.log) + printf "Tbench-$1 avg freq: $avg_freq\n" | tee -a $OUTFILE_TBENCH.result + + grep "Tbench-$1-#" $OUTFILE_TBENCH.result | grep "avg load:" | awk '{print $NF}' > $OUTFILE_TBENCH-load-$1.log + avg_load=$(awk 'BEGIN {sum=0};{sum += $1};END {print sum/'$LOOP_TIMES'}' $OUTFILE_TBENCH-load-$1.log) + printf "Tbench-$1 avg load: $avg_load\n" | tee -a $OUTFILE_TBENCH.result + + grep "Tbench-$1-#" $OUTFILE_TBENCH.result | grep "throughput(MB/s):" | awk '{print $NF}' > $OUTFILE_TBENCH-throughput-$1.log + tp_sum=$(awk 'BEGIN {sum=0};{sum += $1};END {print sum}' $OUTFILE_TBENCH-throughput-$1.log) + printf "Tbench-$1 total throughput(MB/s): $tp_sum\n" | tee -a $OUTFILE_TBENCH.result + + avg_tp=$(awk 'BEGIN {sum=0};{sum += $1};END {print sum/'$LOOP_TIMES'}' $OUTFILE_TBENCH-throughput-$1.log) + printf "Tbench-$1 avg throughput(MB/s): $avg_tp\n" | tee -a $OUTFILE_TBENCH.result + + grep "Tbench-$1-#" $OUTFILE_TBENCH.result | grep "power consumption(J):" | awk '{print $NF}' > $OUTFILE_TBENCH-energy-$1.log + en_sum=$(awk 'BEGIN {sum=0};{sum += $1};END {print sum}' $OUTFILE_TBENCH-energy-$1.log) + printf "Tbench-$1 total power consumption(J): $en_sum\n" | tee -a $OUTFILE_TBENCH.result + + avg_en=$(awk 'BEGIN {sum=0};{sum += $1};END {print sum/'$LOOP_TIMES'}' $OUTFILE_TBENCH-energy-$1.log) + printf "Tbench-$1 avg power consumption(J): $avg_en\n" | tee -a $OUTFILE_TBENCH.result + + # Permance is throughput per second, denoted T/t, where T is throught rendered in t seconds. + # It is well known that P=E/t, where P is power measured in watts(W), E is energy measured in joules(J), + # and t is time measured in seconds(s). This means that performance per watt becomes + # T/t T/t T + # --- = --- = --- + # P E/t E + # with unit given by MB per joule. + ppw=`echo "scale=4;($TIME_LIMIT-1)*$avg_tp/$avg_en" | bc | awk '{printf "%.4f", $0}'` + printf "Tbench-$1 performance per watt(MB/J): $ppw\n" | tee -a $OUTFILE_TBENCH.result + printf "\n" | tee -a $OUTFILE_TBENCH.result + + driver_name=`echo $(scaling_name)` + store_csv_tbench "$driver_name-$1" "Average" $avg_des_perf $avg_freq $avg_load $avg_tp $avg_en $ppw +} + +# $1: base scaling_driver $2: base governor $3: comparative scaling_driver $4: comparative governor +__calc_comp_tbench() +{ + base=`grep "$1-$2" $OUTFILE_TBENCH.csv | grep "Average"` + comp=`grep "$3-$4" $OUTFILE_TBENCH.csv | grep "Average"` + + if [ -n "$base" -a -n "$comp" ]; then + printf "\n==================================================\n" | tee -a $OUTFILE_TBENCH.result + printf "Tbench comparison $1-$2 VS $3-$4" | tee -a $OUTFILE_TBENCH.result + printf "\n==================================================\n" | tee -a $OUTFILE_TBENCH.result + + # get the base values + des_perf_base=`echo "$base" | awk '{print $3}' | sed s/,//` + freq_base=`echo "$base" | awk '{print $4}' | sed s/,//` + load_base=`echo "$base" | awk '{print $5}' | sed s/,//` + perf_base=`echo "$base" | awk '{print $6}' | sed s/,//` + energy_base=`echo "$base" | awk '{print $7}' | sed s/,//` + ppw_base=`echo "$base" | awk '{print $8}' | sed s/,//` + + # get the comparative values + des_perf_comp=`echo "$comp" | awk '{print $3}' | sed s/,//` + freq_comp=`echo "$comp" | awk '{print $4}' | sed s/,//` + load_comp=`echo "$comp" | awk '{print $5}' | sed s/,//` + perf_comp=`echo "$comp" | awk '{print $6}' | sed s/,//` + energy_comp=`echo "$comp" | awk '{print $7}' | sed s/,//` + ppw_comp=`echo "$comp" | awk '{print $8}' | sed s/,//` + + # compare the base and comp values + des_perf_drop=`echo "scale=4;($des_perf_comp-$des_perf_base)*100/$des_perf_base" | bc | awk '{printf "%.4f", $0}'` + printf "Tbench-$1 des perf base: $des_perf_base comprison: $des_perf_comp percent: $des_perf_drop\n" | tee -a $OUTFILE_TBENCH.result + + freq_drop=`echo "scale=4;($freq_comp-$freq_base)*100/$freq_base" | bc | awk '{printf "%.4f", $0}'` + printf "Tbench-$1 freq base: $freq_base comprison: $freq_comp percent: $freq_drop\n" | tee -a $OUTFILE_TBENCH.result + + load_drop=`echo "scale=4;($load_comp-$load_base)*100/$load_base" | bc | awk '{printf "%.4f", $0}'` + printf "Tbench-$1 load base: $load_base comprison: $load_comp percent: $load_drop\n" | tee -a $OUTFILE_TBENCH.result + + perf_drop=`echo "scale=4;($perf_comp-$perf_base)*100/$perf_base" | bc | awk '{printf "%.4f", $0}'` + printf "Tbench-$1 perf base: $perf_base comprison: $perf_comp percent: $perf_drop\n" | tee -a $OUTFILE_TBENCH.result + + energy_drop=`echo "scale=4;($energy_comp-$energy_base)*100/$energy_base" | bc | awk '{printf "%.4f", $0}'` + printf "Tbench-$1 energy base: $energy_base comprison: $energy_comp percent: $energy_drop\n" | tee -a $OUTFILE_TBENCH.result + + ppw_drop=`echo "scale=4;($ppw_comp-$ppw_base)*100/$ppw_base" | bc | awk '{printf "%.4f", $0}'` + printf "Tbench-$1 performance per watt base: $ppw_base comprison: $ppw_comp percent: $ppw_drop\n" | tee -a $OUTFILE_TBENCH.result + printf "\n" | tee -a $OUTFILE_TBENCH.result + + store_csv_tbench "$1-$2 VS $3-$4" "Comprison(%)" "$des_perf_drop" "$freq_drop" "$load_drop" "$perf_drop" "$energy_drop" "$ppw_drop" + fi +} + +# calculate the comparison(%) +calc_comp_tbench() +{ + # acpi-cpufreq-ondemand VS acpi-cpufreq-schedutil + __calc_comp_tbench ${all_scaling_names[0]} ${tbench_governors[0]} ${all_scaling_names[0]} ${tbench_governors[1]} + + # amd-pstate-ondemand VS amd-pstate-schedutil + __calc_comp_tbench ${all_scaling_names[1]} ${tbench_governors[0]} ${all_scaling_names[1]} ${tbench_governors[1]} + + # acpi-cpufreq-ondemand VS amd-pstate-ondemand + __calc_comp_tbench ${all_scaling_names[0]} ${tbench_governors[0]} ${all_scaling_names[1]} ${tbench_governors[0]} + + # acpi-cpufreq-schedutil VS amd-pstate-schedutil + __calc_comp_tbench ${all_scaling_names[0]} ${tbench_governors[1]} ${all_scaling_names[1]} ${tbench_governors[1]} +} + +# $1: file_name, $2: title, $3: ylable, $4: column +plot_png_tbench() +{ + # all_scaling_names[1] all_scaling_names[0] flag + # amd-pstate acpi-cpufreq + # N N 0 + # N Y 1 + # Y N 2 + # Y Y 3 + ret=`grep -c "${all_scaling_names[1]}" $OUTFILE_TBENCH.csv` + if [ $ret -eq 0 ]; then + ret=`grep -c "${all_scaling_names[0]}" $OUTFILE_TBENCH.csv` + if [ $ret -eq 0 ]; then + flag=0 + else + flag=1 + fi + else + ret=`grep -c "${all_scaling_names[0]}" $OUTFILE_TBENCH.csv` + if [ $ret -eq 0 ]; then + flag=2 + else + flag=3 + fi + fi + + gnuplot << EOF + set term png + set output "$1" + + set title "$2" + set xlabel "Test Cycles (round)" + set ylabel "$3" + + set grid + set style data histogram + set style fill solid 0.5 border + set boxwidth 0.8 + + if ($flag == 1) { + plot \ + "<(sed -n -e 's/,//g' -e '/${all_scaling_names[0]}-${tbench_governors[0]}/p' $OUTFILE_TBENCH.csv)" using $4:xtic(2) title "${all_scaling_names[0]}-${tbench_governors[0]}", \ + "<(sed -n -e 's/,//g' -e '/${all_scaling_names[0]}-${tbench_governors[1]}/p' $OUTFILE_TBENCH.csv)" using $4:xtic(2) title "${all_scaling_names[0]}-${tbench_governors[1]}" + } else { + if ($flag == 2) { + plot \ + "<(sed -n -e 's/,//g' -e '/${all_scaling_names[1]}-${tbench_governors[0]}/p' $OUTFILE_TBENCH.csv)" using $4:xtic(2) title "${all_scaling_names[1]}-${tbench_governors[0]}", \ + "<(sed -n -e 's/,//g' -e '/${all_scaling_names[1]}-${tbench_governors[1]}/p' $OUTFILE_TBENCH.csv)" using $4:xtic(2) title "${all_scaling_names[1]}-${tbench_governors[1]}" + } else { + if ($flag == 3 ) { + plot \ + "<(sed -n -e 's/,//g' -e '/${all_scaling_names[0]}-${tbench_governors[0]}/p' $OUTFILE_TBENCH.csv)" using $4:xtic(2) title "${all_scaling_names[0]}-${tbench_governors[0]}", \ + "<(sed -n -e 's/,//g' -e '/${all_scaling_names[0]}-${tbench_governors[1]}/p' $OUTFILE_TBENCH.csv)" using $4:xtic(2) title "${all_scaling_names[0]}-${tbench_governors[1]}", \ + "<(sed -n -e 's/,//g' -e '/${all_scaling_names[1]}-${tbench_governors[0]}/p' $OUTFILE_TBENCH.csv)" using $4:xtic(2) title "${all_scaling_names[1]}-${tbench_governors[0]}", \ + "<(sed -n -e 's/,//g' -e '/${all_scaling_names[1]}-${tbench_governors[1]}/p' $OUTFILE_TBENCH.csv)" using $4:xtic(2) title "${all_scaling_names[1]}-${tbench_governors[1]}" + } + } + } + quit +EOF +} + +amd_pstate_tbench() +{ + printf "\n---------------------------------------------\n" + printf "*** Running tbench ***" + printf "\n---------------------------------------------\n" + + pre_clear_tbench + + get_lines_csv_tbench "Governor" + if [ $? -eq 0 ]; then + # add titles and unit for csv file + store_csv_tbench "Governor" "Round" "Des-perf" "Freq" "Load" "Performance" "Energy" "Performance Per Watt" + store_csv_tbench "Unit" "" "" "GHz" "" "MB/s" "J" "MB/J" + fi + + backup_governor + for governor in ${tbench_governors[*]} ; do + printf "\nSpecified governor is $governor\n\n" + switch_governor $governor + loop_tbench $governor + gather_tbench $governor + done + restore_governor + + plot_png_tbench "tbench_perfromance.png" "Tbench Benchmark Performance" "Performance" 6 + plot_png_tbench "tbench_energy.png" "Tbench Benchmark Energy" "Energy (J)" 7 + plot_png_tbench "tbench_ppw.png" "Tbench Benchmark Performance Per Watt" "Performance Per Watt (MB/J)" 8 + + calc_comp_tbench + + post_clear_tbench +} diff --git a/tools/testing/selftests/efivarfs/efivarfs.sh b/tools/testing/selftests/efivarfs/efivarfs.sh index a90f394f9aa9..d374878cc0ba 100755 --- a/tools/testing/selftests/efivarfs/efivarfs.sh +++ b/tools/testing/selftests/efivarfs/efivarfs.sh @@ -87,6 +87,11 @@ test_create_read() { local file=$efivarfs_mount/$FUNCNAME-$test_guid ./create-read $file + if [ $? -ne 0 ]; then + echo "create and read $file failed" + file_cleanup $file + exit 1 + fi file_cleanup $file } diff --git a/tools/testing/selftests/ftrace/test.d/ftrace/func_event_triggers.tc b/tools/testing/selftests/ftrace/test.d/ftrace/func_event_triggers.tc index 8d26d5505808..3eea2abf68f9 100644 --- a/tools/testing/selftests/ftrace/test.d/ftrace/func_event_triggers.tc +++ b/tools/testing/selftests/ftrace/test.d/ftrace/func_event_triggers.tc @@ -38,11 +38,18 @@ cnt_trace() { test_event_enabled() { val=$1 + check_times=10 # wait for 10 * SLEEP_TIME at most - e=`cat $EVENT_ENABLE` - if [ "$e" != $val ]; then - fail "Expected $val but found $e" - fi + while [ $check_times -ne 0 ]; do + e=`cat $EVENT_ENABLE` + if [ "$e" == $val ]; then + return 0 + fi + sleep $SLEEP_TIME + check_times=$((check_times - 1)) + done + + fail "Expected $val but found $e" } run_enable_disable() { diff --git a/tools/testing/selftests/ftrace/test.d/functions b/tools/testing/selftests/ftrace/test.d/functions index 5f6cbec847fc..779f3e62ec90 100644 --- a/tools/testing/selftests/ftrace/test.d/functions +++ b/tools/testing/selftests/ftrace/test.d/functions @@ -142,9 +142,15 @@ finish_ftrace() { check_requires() { # Check required files and tracers for i in "$@" ; do + p=${i%:program} r=${i%:README} t=${i%:tracer} - if [ $t != $i ]; then + if [ $p != $i ]; then + if ! which $p ; then + echo "Required program $p is not found." + exit_unresolved + fi + elif [ $t != $i ]; then if ! grep -wq $t available_tracers ; then echo "Required tracer $t is not configured." exit_unsupported diff --git a/tools/testing/selftests/ftrace/test.d/preemptirq/irqsoff_tracer.tc b/tools/testing/selftests/ftrace/test.d/preemptirq/irqsoff_tracer.tc index 22bff122b933..ba1038953873 100644 --- a/tools/testing/selftests/ftrace/test.d/preemptirq/irqsoff_tracer.tc +++ b/tools/testing/selftests/ftrace/test.d/preemptirq/irqsoff_tracer.tc @@ -46,10 +46,10 @@ cat trace grep -q "tracer: preemptoff" trace || fail # Check the end of the section -egrep -q "5.....us : <stack trace>" trace || fail +grep -E -q "5.....us : <stack trace>" trace || fail # Check for 500ms of latency -egrep -q "latency: 5..... us" trace || fail +grep -E -q "latency: 5..... us" trace || fail reset_tracer @@ -69,10 +69,10 @@ cat trace grep -q "tracer: irqsoff" trace || fail # Check the end of the section -egrep -q "5.....us : <stack trace>" trace || fail +grep -E -q "5.....us : <stack trace>" trace || fail # Check for 500ms of latency -egrep -q "latency: 5..... us" trace || fail +grep -E -q "latency: 5..... us" trace || fail reset_tracer exit 0 diff --git a/tools/testing/selftests/ftrace/test.d/tracer/wakeup.tc b/tools/testing/selftests/ftrace/test.d/tracer/wakeup.tc index 11be10e1bf96..e8f0fac9a110 100644 --- a/tools/testing/selftests/ftrace/test.d/tracer/wakeup.tc +++ b/tools/testing/selftests/ftrace/test.d/tracer/wakeup.tc @@ -1,12 +1,7 @@ #!/bin/sh # SPDX-License-Identifier: GPL-2.0 # description: Test wakeup tracer -# requires: wakeup:tracer - -if ! which chrt ; then - echo "chrt is not found. This test requires nice command." - exit_unresolved -fi +# requires: wakeup:tracer chrt:program echo wakeup > current_tracer echo 1 > tracing_on diff --git a/tools/testing/selftests/ftrace/test.d/tracer/wakeup_rt.tc b/tools/testing/selftests/ftrace/test.d/tracer/wakeup_rt.tc index 3a77198b3c69..79807656785b 100644 --- a/tools/testing/selftests/ftrace/test.d/tracer/wakeup_rt.tc +++ b/tools/testing/selftests/ftrace/test.d/tracer/wakeup_rt.tc @@ -1,12 +1,7 @@ #!/bin/sh # SPDX-License-Identifier: GPL-2.0 # description: Test wakeup RT tracer -# requires: wakeup_rt:tracer - -if ! which chrt ; then - echo "chrt is not found. This test requires chrt command." - exit_unresolved -fi +# requires: wakeup_rt:tracer chrt:program echo wakeup_rt > current_tracer echo 1 > tracing_on diff --git a/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-field-variable-support.tc b/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-field-variable-support.tc index 41119e0440e9..04c5dd7d0acc 100644 --- a/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-field-variable-support.tc +++ b/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-field-variable-support.tc @@ -1,7 +1,7 @@ #!/bin/sh # SPDX-License-Identifier: GPL-2.0 # description: event trigger - test field variable support -# requires: set_event synthetic_events events/sched/sched_process_fork/hist +# requires: set_event synthetic_events events/sched/sched_process_fork/hist ping:program fail() { #msg echo $1 diff --git a/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-inter-event-combined-hist.tc b/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-inter-event-combined-hist.tc index 9098f1e7433f..f7447d800899 100644 --- a/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-inter-event-combined-hist.tc +++ b/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-inter-event-combined-hist.tc @@ -1,7 +1,7 @@ #!/bin/sh # SPDX-License-Identifier: GPL-2.0 # description: event trigger - test inter-event combined histogram trigger -# requires: set_event synthetic_events events/sched/sched_process_fork/hist +# requires: set_event synthetic_events events/sched/sched_process_fork/hist ping:program fail() { #msg echo $1 diff --git a/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-onchange-action-hist.tc b/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-onchange-action-hist.tc index adaabb873ed4..91339c130832 100644 --- a/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-onchange-action-hist.tc +++ b/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-onchange-action-hist.tc @@ -1,7 +1,7 @@ #!/bin/sh # SPDX-License-Identifier: GPL-2.0 # description: event trigger - test inter-event histogram trigger onchange action -# requires: set_event "onchange(var)":README +# requires: set_event "onchange(var)":README ping:program fail() { #msg echo $1 diff --git a/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-onmatch-action-hist.tc b/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-onmatch-action-hist.tc index 20e39471052e..d645abcf11c4 100644 --- a/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-onmatch-action-hist.tc +++ b/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-onmatch-action-hist.tc @@ -1,7 +1,7 @@ #!/bin/sh # SPDX-License-Identifier: GPL-2.0 # description: event trigger - test inter-event histogram trigger onmatch action -# requires: set_event synthetic_events events/sched/sched_process_fork/hist +# requires: set_event synthetic_events events/sched/sched_process_fork/hist ping:program fail() { #msg echo $1 diff --git a/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-onmatch-onmax-action-hist.tc b/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-onmatch-onmax-action-hist.tc index f4b03ab7c287..c369247efb35 100644 --- a/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-onmatch-onmax-action-hist.tc +++ b/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-onmatch-onmax-action-hist.tc @@ -1,7 +1,7 @@ #!/bin/sh # SPDX-License-Identifier: GPL-2.0 # description: event trigger - test inter-event histogram trigger onmatch-onmax action -# requires: set_event synthetic_events events/sched/sched_process_fork/hist +# requires: set_event synthetic_events events/sched/sched_process_fork/hist ping:program fail() { #msg echo $1 diff --git a/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-onmax-action-hist.tc b/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-onmax-action-hist.tc index 71c9b5911c70..e28dc5f11b2b 100644 --- a/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-onmax-action-hist.tc +++ b/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-onmax-action-hist.tc @@ -1,7 +1,7 @@ #!/bin/sh # SPDX-License-Identifier: GPL-2.0 # description: event trigger - test inter-event histogram trigger onmax action -# requires: set_event synthetic_events events/sched/sched_process_fork/hist +# requires: set_event synthetic_events events/sched/sched_process_fork/hist ping:program fail() { #msg echo $1 diff --git a/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-snapshot-action-hist.tc b/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-snapshot-action-hist.tc index 67fa328b830f..147967e86584 100644 --- a/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-snapshot-action-hist.tc +++ b/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-snapshot-action-hist.tc @@ -1,7 +1,7 @@ #!/bin/sh # SPDX-License-Identifier: GPL-2.0 # description: event trigger - test inter-event histogram trigger snapshot action -# requires: set_event snapshot events/sched/sched_process_fork/hist "onchange(var)":README "snapshot()":README +# requires: set_event snapshot events/sched/sched_process_fork/hist "onchange(var)":README "snapshot()":README ping:program fail() { #msg echo $1 diff --git a/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-synthetic-eprobe.tc b/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-synthetic-eprobe.tc index 6461c375694f..c2a8ab01e13b 100644 --- a/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-synthetic-eprobe.tc +++ b/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-synthetic-eprobe.tc @@ -14,7 +14,7 @@ FIELD="filename" SYNTH="synth_open" EPROBE="eprobe_open" -echo "$SYNTH u64 filename; s64 ret;" > synthetic_events +echo "$SYNTH unsigned long filename; long ret;" > synthetic_events echo "hist:keys=common_pid:__arg__1=$FIELD" > events/$SYSTEM/$START/trigger echo "hist:keys=common_pid:filename=\$__arg__1,ret=ret:onmatch($SYSTEM.$START).trace($SYNTH,\$filename,\$ret)" > events/$SYSTEM/$END/trigger diff --git a/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-synthetic-event-dynstring.tc b/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-synthetic-event-dynstring.tc index 3d65c856eca3..213d890ed188 100644 --- a/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-synthetic-event-dynstring.tc +++ b/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-synthetic-event-dynstring.tc @@ -1,7 +1,7 @@ #!/bin/sh # SPDX-License-Identifier: GPL-2.0 # description: event trigger - test inter-event histogram trigger trace action with dynamic string param -# requires: set_event synthetic_events events/sched/sched_process_exec/hist "char name[]' >> synthetic_events":README +# requires: set_event synthetic_events events/sched/sched_process_exec/hist "char name[]' >> synthetic_events":README ping:program fail() { #msg echo $1 diff --git a/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-trace-action-hist.tc b/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-trace-action-hist.tc index c126d2350a6d..d7312047ce28 100644 --- a/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-trace-action-hist.tc +++ b/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-trace-action-hist.tc @@ -1,7 +1,7 @@ #!/bin/sh # SPDX-License-Identifier: GPL-2.0 # description: event trigger - test inter-event histogram trigger trace action -# requires: set_event synthetic_events events/sched/sched_process_fork/hist "trace(<synthetic_event>":README +# requires: set_event synthetic_events events/sched/sched_process_fork/hist "trace(<synthetic_event>":README ping:program fail() { #msg echo $1 diff --git a/tools/testing/selftests/gpio/gpio-sim.sh b/tools/testing/selftests/gpio/gpio-sim.sh index 341e3de00896..9f539d454ee4 100755 --- a/tools/testing/selftests/gpio/gpio-sim.sh +++ b/tools/testing/selftests/gpio/gpio-sim.sh @@ -27,7 +27,7 @@ remove_chip() { continue fi - LINES=`ls $CONFIGFS_DIR/$CHIP/$BANK/ | egrep ^line` + LINES=`ls $CONFIGFS_DIR/$CHIP/$BANK/ | grep -E ^line` if [ "$?" = 0 ]; then for LINE in $LINES; do if [ -e $CONFIGFS_DIR/$CHIP/$BANK/$LINE/hog ]; then diff --git a/tools/testing/selftests/kselftest_deps.sh b/tools/testing/selftests/kselftest_deps.sh index 708cb5429633..7424a1f5babc 100755 --- a/tools/testing/selftests/kselftest_deps.sh +++ b/tools/testing/selftests/kselftest_deps.sh @@ -90,7 +90,7 @@ pass_libs=() pass_cnt=0 # Get all TARGETS from selftests Makefile -targets=$(egrep "^TARGETS +|^TARGETS =" Makefile | cut -d "=" -f2) +targets=$(grep -E "^TARGETS +|^TARGETS =" Makefile | cut -d "=" -f2) # Single test case if [ $# -eq 2 ] diff --git a/tools/testing/selftests/lib.mk b/tools/testing/selftests/lib.mk index a3ea3d4a206d..291144c284fb 100644 --- a/tools/testing/selftests/lib.mk +++ b/tools/testing/selftests/lib.mk @@ -123,6 +123,11 @@ endef clean: $(CLEAN) +# Enables to extend CFLAGS and LDFLAGS from command line, e.g. +# make USERCFLAGS=-Werror USERLDFLAGS=-static +CFLAGS += $(USERCFLAGS) +LDFLAGS += $(USERLDFLAGS) + # When make O= with kselftest target from main level # the following aren't defined. # diff --git a/tools/testing/selftests/rtc/rtctest.c b/tools/testing/selftests/rtc/rtctest.c index 2b9d929a24ed..63ce02d1d5cc 100644 --- a/tools/testing/selftests/rtc/rtctest.c +++ b/tools/testing/selftests/rtc/rtctest.c @@ -31,7 +31,6 @@ FIXTURE(rtc) { FIXTURE_SETUP(rtc) { self->fd = open(rtc_file, O_RDONLY); - ASSERT_NE(-1, self->fd); } FIXTURE_TEARDOWN(rtc) { @@ -42,6 +41,10 @@ TEST_F(rtc, date_read) { int rc; struct rtc_time rtc_tm; + if (self->fd == -1 && errno == ENOENT) + SKIP(return, "Skipping test since %s does not exist", rtc_file); + ASSERT_NE(-1, self->fd); + /* Read the RTC time/date */ rc = ioctl(self->fd, RTC_RD_TIME, &rtc_tm); ASSERT_NE(-1, rc); @@ -85,6 +88,10 @@ TEST_F_TIMEOUT(rtc, date_read_loop, READ_LOOP_DURATION_SEC + 2) { struct rtc_time rtc_tm; time_t start_rtc_read, prev_rtc_read; + if (self->fd == -1 && errno == ENOENT) + SKIP(return, "Skipping test since %s does not exist", rtc_file); + ASSERT_NE(-1, self->fd); + TH_LOG("Continuously reading RTC time for %ds (with %dms breaks after every read).", READ_LOOP_DURATION_SEC, READ_LOOP_SLEEP_MS); @@ -119,6 +126,10 @@ TEST_F_TIMEOUT(rtc, uie_read, NUM_UIE + 2) { int i, rc, irq = 0; unsigned long data; + if (self->fd == -1 && errno == ENOENT) + SKIP(return, "Skipping test since %s does not exist", rtc_file); + ASSERT_NE(-1, self->fd); + /* Turn on update interrupts */ rc = ioctl(self->fd, RTC_UIE_ON, 0); if (rc == -1) { @@ -144,6 +155,10 @@ TEST_F(rtc, uie_select) { int i, rc, irq = 0; unsigned long data; + if (self->fd == -1 && errno == ENOENT) + SKIP(return, "Skipping test since %s does not exist", rtc_file); + ASSERT_NE(-1, self->fd); + /* Turn on update interrupts */ rc = ioctl(self->fd, RTC_UIE_ON, 0); if (rc == -1) { @@ -183,6 +198,10 @@ TEST_F(rtc, alarm_alm_set) { time_t secs, new; int rc; + if (self->fd == -1 && errno == ENOENT) + SKIP(return, "Skipping test since %s does not exist", rtc_file); + ASSERT_NE(-1, self->fd); + rc = ioctl(self->fd, RTC_RD_TIME, &tm); ASSERT_NE(-1, rc); @@ -237,6 +256,10 @@ TEST_F(rtc, alarm_wkalm_set) { time_t secs, new; int rc; + if (self->fd == -1 && errno == ENOENT) + SKIP(return, "Skipping test since %s does not exist", rtc_file); + ASSERT_NE(-1, self->fd); + rc = ioctl(self->fd, RTC_RD_TIME, &alarm.time); ASSERT_NE(-1, rc); @@ -285,6 +308,10 @@ TEST_F_TIMEOUT(rtc, alarm_alm_set_minute, 65) { time_t secs, new; int rc; + if (self->fd == -1 && errno == ENOENT) + SKIP(return, "Skipping test since %s does not exist", rtc_file); + ASSERT_NE(-1, self->fd); + rc = ioctl(self->fd, RTC_RD_TIME, &tm); ASSERT_NE(-1, rc); @@ -339,6 +366,10 @@ TEST_F_TIMEOUT(rtc, alarm_wkalm_set_minute, 65) { time_t secs, new; int rc; + if (self->fd == -1 && errno == ENOENT) + SKIP(return, "Skipping test since %s does not exist", rtc_file); + ASSERT_NE(-1, self->fd); + rc = ioctl(self->fd, RTC_RD_TIME, &alarm.time); ASSERT_NE(-1, rc); diff --git a/tools/testing/selftests/splice/short_splice_read.sh b/tools/testing/selftests/splice/short_splice_read.sh index 22b6c8910b18..4710e09f49fa 100755 --- a/tools/testing/selftests/splice/short_splice_read.sh +++ b/tools/testing/selftests/splice/short_splice_read.sh @@ -127,7 +127,7 @@ expect_success "proc_handler: special read splice" test_splice /proc/sys/kernel/ if ! [ -d /sys/module/test_module/sections ] ; then expect_success "test_module kernel module load" modprobe test_module fi -expect_failure "kernfs attr splice" test_splice /sys/module/test_module/coresize -expect_failure "kernfs binattr splice" test_splice /sys/module/test_module/sections/.init.text +expect_success "kernfs attr splice" test_splice /sys/module/test_module/coresize +expect_success "kernfs binattr splice" test_splice /sys/module/test_module/sections/.init.text exit $ret diff --git a/tools/testing/selftests/tpm2/Makefile b/tools/testing/selftests/tpm2/Makefile index 1a5db1eb8ed5..a9bf9459fb25 100644 --- a/tools/testing/selftests/tpm2/Makefile +++ b/tools/testing/selftests/tpm2/Makefile @@ -1,5 +1,5 @@ # SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) include ../lib.mk -TEST_PROGS := test_smoke.sh test_space.sh +TEST_PROGS := test_smoke.sh test_space.sh test_async.sh TEST_PROGS_EXTENDED := tpm2.py tpm2_tests.py diff --git a/tools/testing/selftests/tpm2/test_async.sh b/tools/testing/selftests/tpm2/test_async.sh new file mode 100755 index 000000000000..43bf5bd772fd --- /dev/null +++ b/tools/testing/selftests/tpm2/test_async.sh @@ -0,0 +1,10 @@ +#!/bin/sh +# SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) + +# Kselftest framework requirement - SKIP code is 4. +ksft_skip=4 + +[ -e /dev/tpm0 ] || exit $ksft_skip +[ -e /dev/tpmrm0 ] || exit $ksft_skip + +python3 -m unittest -v tpm2_tests.AsyncTest diff --git a/tools/testing/selftests/tpm2/test_smoke.sh b/tools/testing/selftests/tpm2/test_smoke.sh index 3e5ff29ee1dd..58af963e5b55 100755 --- a/tools/testing/selftests/tpm2/test_smoke.sh +++ b/tools/testing/selftests/tpm2/test_smoke.sh @@ -7,4 +7,3 @@ ksft_skip=4 [ -e /dev/tpm0 ] || exit $ksft_skip python3 -m unittest -v tpm2_tests.SmokeTest -python3 -m unittest -v tpm2_tests.AsyncTest diff --git a/tools/testing/selftests/vDSO/vdso_test_getcpu.c b/tools/testing/selftests/vDSO/vdso_test_getcpu.c index fc25ede131b8..1df5d057d79f 100644 --- a/tools/testing/selftests/vDSO/vdso_test_getcpu.c +++ b/tools/testing/selftests/vDSO/vdso_test_getcpu.c @@ -14,7 +14,11 @@ #include "../kselftest.h" #include "parse_vdso.h" +#if defined(__riscv) +const char *version = "LINUX_4.15"; +#else const char *version = "LINUX_2.6"; +#endif const char *name = "__vdso_getcpu"; struct getcpu_cache; diff --git a/tools/testing/selftests/vDSO/vdso_test_gettimeofday.c b/tools/testing/selftests/vDSO/vdso_test_gettimeofday.c index 8ccc73ed8240..e411f287a426 100644 --- a/tools/testing/selftests/vDSO/vdso_test_gettimeofday.c +++ b/tools/testing/selftests/vDSO/vdso_test_gettimeofday.c @@ -27,6 +27,9 @@ #if defined(__aarch64__) const char *version = "LINUX_2.6.39"; const char *name = "__kernel_gettimeofday"; +#elif defined(__riscv) +const char *version = "LINUX_4.15"; +const char *name = "__vdso_gettimeofday"; #else const char *version = "LINUX_2.6"; const char *name = "__vdso_gettimeofday"; diff --git a/tools/testing/selftests/watchdog/watchdog-test.c b/tools/testing/selftests/watchdog/watchdog-test.c index f45e510500c0..bc71cbca0dde 100644 --- a/tools/testing/selftests/watchdog/watchdog-test.c +++ b/tools/testing/selftests/watchdog/watchdog-test.c @@ -1,6 +1,14 @@ // SPDX-License-Identifier: GPL-2.0 /* - * Watchdog Driver Test Program +* Watchdog Driver Test Program +* - Tests all ioctls +* - Tests Magic Close - CONFIG_WATCHDOG_NOWAYOUT +* - Could be tested against softdog driver on systems that +* don't have watchdog hardware. +* - TODO: +* - Enhance test to add coverage for WDIOC_GETTEMP. +* +* Reference: Documentation/watchdog/watchdog-api.rst */ #include <errno.h> @@ -19,13 +27,14 @@ int fd; const char v = 'V'; -static const char sopts[] = "bdehp:t:Tn:NLf:i"; +static const char sopts[] = "bdehp:st:Tn:NLf:i"; static const struct option lopts[] = { {"bootstatus", no_argument, NULL, 'b'}, {"disable", no_argument, NULL, 'd'}, {"enable", no_argument, NULL, 'e'}, {"help", no_argument, NULL, 'h'}, {"pingrate", required_argument, NULL, 'p'}, + {"status", no_argument, NULL, 's'}, {"timeout", required_argument, NULL, 't'}, {"gettimeout", no_argument, NULL, 'T'}, {"pretimeout", required_argument, NULL, 'n'}, @@ -74,6 +83,7 @@ static void usage(char *progname) printf(" -f, --file\t\tOpen watchdog device file\n"); printf("\t\t\tDefault is /dev/watchdog\n"); printf(" -i, --info\t\tShow watchdog_info\n"); + printf(" -s, --status\t\tGet status & supported features\n"); printf(" -b, --bootstatus\tGet last boot status (Watchdog/POR)\n"); printf(" -d, --disable\t\tTurn off the watchdog timer\n"); printf(" -e, --enable\t\tTurn on the watchdog timer\n"); @@ -91,6 +101,73 @@ static void usage(char *progname) printf("Example: %s -t 12 -T -n 7 -N\n", progname); } +struct wdiof_status { + int flag; + const char *status_str; +}; + +#define WDIOF_NUM_STATUS 8 + +static const struct wdiof_status wdiof_status[WDIOF_NUM_STATUS] = { + {WDIOF_SETTIMEOUT, "Set timeout (in seconds)"}, + {WDIOF_MAGICCLOSE, "Supports magic close char"}, + {WDIOF_PRETIMEOUT, "Pretimeout (in seconds), get/set"}, + {WDIOF_ALARMONLY, "Watchdog triggers a management or other external alarm not a reboot"}, + {WDIOF_KEEPALIVEPING, "Keep alive ping reply"}, + {WDIOS_DISABLECARD, "Turn off the watchdog timer"}, + {WDIOS_ENABLECARD, "Turn on the watchdog timer"}, + {WDIOS_TEMPPANIC, "Kernel panic on temperature trip"}, +}; + +static void print_status(int flags) +{ + int wdiof = 0; + + if (flags == WDIOS_UNKNOWN) { + printf("Unknown status error from WDIOC_GETSTATUS\n"); + return; + } + + for (wdiof = 0; wdiof < WDIOF_NUM_STATUS; wdiof++) { + if (flags & wdiof_status[wdiof].flag) + printf("Support/Status: %s\n", + wdiof_status[wdiof].status_str); + } +} + +#define WDIOF_NUM_BOOTSTATUS 7 + +static const struct wdiof_status wdiof_bootstatus[WDIOF_NUM_BOOTSTATUS] = { + {WDIOF_OVERHEAT, "Reset due to CPU overheat"}, + {WDIOF_FANFAULT, "Fan failed"}, + {WDIOF_EXTERN1, "External relay 1"}, + {WDIOF_EXTERN2, "External relay 2"}, + {WDIOF_POWERUNDER, "Power bad/power fault"}, + {WDIOF_CARDRESET, "Card previously reset the CPU"}, + {WDIOF_POWEROVER, "Power over voltage"}, +}; + +static void print_boot_status(int flags) +{ + int wdiof = 0; + + if (flags == WDIOF_UNKNOWN) { + printf("Unknown flag error from WDIOC_GETBOOTSTATUS\n"); + return; + } + + if (flags == 0) { + printf("Last boot is caused by: Power-On-Reset\n"); + return; + } + + for (wdiof = 0; wdiof < WDIOF_NUM_BOOTSTATUS; wdiof++) { + if (flags & wdiof_bootstatus[wdiof].flag) + printf("Last boot is caused by: %s\n", + wdiof_bootstatus[wdiof].status_str); + } +} + int main(int argc, char *argv[]) { int flags; @@ -100,6 +177,7 @@ int main(int argc, char *argv[]) int oneshot = 0; char *file = "/dev/watchdog"; struct watchdog_info info; + int temperature; setbuf(stdout, NULL); @@ -140,8 +218,7 @@ int main(int argc, char *argv[]) oneshot = 1; ret = ioctl(fd, WDIOC_GETBOOTSTATUS, &flags); if (!ret) - printf("Last boot is caused by: %s.\n", (flags != 0) ? - "Watchdog" : "Power-On-Reset"); + print_boot_status(flags); else printf("WDIOC_GETBOOTSTATUS error '%s'\n", strerror(errno)); break; @@ -171,6 +248,21 @@ int main(int argc, char *argv[]) ping_rate = DEFAULT_PING_RATE; printf("Watchdog ping rate set to %u seconds.\n", ping_rate); break; + case 's': + flags = 0; + oneshot = 1; + ret = ioctl(fd, WDIOC_GETSTATUS, &flags); + if (!ret) + print_status(flags); + else + printf("WDIOC_GETSTATUS error '%s'\n", strerror(errno)); + ret = ioctl(fd, WDIOC_GETTEMP, &temperature); + if (ret) + printf("WDIOC_GETTEMP: '%s'\n", strerror(errno)); + else + printf("Temperature %d\n", temperature); + + break; case 't': flags = strtoul(optarg, NULL, 0); ret = ioctl(fd, WDIOC_SETTIMEOUT, &flags); @@ -228,7 +320,7 @@ int main(int argc, char *argv[]) printf(" identity:\t\t%s\n", info.identity); printf(" firmware_version:\t%u\n", info.firmware_version); - printf(" options:\t\t%08x\n", info.options); + print_status(info.options); break; default: @@ -249,6 +341,10 @@ int main(int argc, char *argv[]) sleep(ping_rate); } end: + /* + * Send specific magic character 'V' just in case Magic Close is + * enabled to ensure watchdog gets disabled on close. + */ ret = write(fd, &v, 1); if (ret < 0) printf("Stopping watchdog ticks failed (%d)...\n", errno); |