From 0ffa7e0aade150bb9911b13f7fccda172da24498 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Fri, 9 Jan 2015 10:29:07 +0530 Subject: cpufreq-tets: Initial git repo Signed-off-by: Viresh Kumar --- .gitignore | 5 ++ README | 16 +++++ cpu.sh | 84 ++++++++++++++++++++++++ cpufreq.sh | 194 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ governor.sh | 86 ++++++++++++++++++++++++ runme.sh | 51 +++++++++++++++ special-tests.sh | 60 +++++++++++++++++ 7 files changed, 496 insertions(+) create mode 100644 .gitignore create mode 100644 README create mode 100755 cpu.sh create mode 100755 cpufreq.sh create mode 100755 governor.sh create mode 100755 runme.sh create mode 100755 special-tests.sh diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e2f3646 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +*.swp +.tmp_versions +cscope.* +ncscope.* +*.patch diff --git a/README b/README new file mode 100644 index 0000000..789eb7e --- /dev/null +++ b/README @@ -0,0 +1,16 @@ +CPUFREQ SANITY TESTS +==================== + +This does a variety of tests to test cpufreq frameworks again bugs. + +Examples: +- hoplugging CPUs in and out. +- switching governors. +- switching frequencies after setting to userspace governor (if available). +- Showing content of all cpufreq files. +- And finally dumping all debug messages in: ${1-debug}.txt and ${1-debug}.full.txt. + +How to run: +========== + +./runme.sh diff --git a/cpu.sh b/cpu.sh new file mode 100755 index 0000000..b5b0620 --- /dev/null +++ b/cpu.sh @@ -0,0 +1,84 @@ +#!/bin/bash +# +# CPU helpers + +source cpufreq.sh + +offline_cpu() +{ + echo 0 > /sys/devices/system/cpu/$1/online +} + +online_cpu() +{ + echo 1 > /sys/devices/system/cpu/$1/online +} + +offline_online_cpu() +{ + offline_cpu $1 + online_cpu $1 +} + +# Offline + online CPUs +# param: number of times we want to run the loop +hotplug_1_by_1() +{ + echo "** Test: Running ${FUNCNAME[0]} for $1 loops **" + echo "" + + for i in `seq 1 $1`; do + for_each_non_boot_cpu offline_online_cpu + done + echo "------------------------------------------------" + echo "" +} + +# Offline all CPUs, followed by online all CPUs +# param: number of times we want to run the loop +hotplug_together() +{ + echo "** Test: Running ${FUNCNAME[0]} for $1 loops **" + echo "" + + for i in `seq 1 $1`; do + for_each_non_boot_cpu offline_cpu + for_each_non_boot_cpu online_cpu + done + echo "------------------------------------------------" + echo "" +} + +for_each_cpu() { + cpus=$(ls $CPU_PATH | grep "cpu[0-9].*") + for cpu in $cpus; do + $@ $cpu + done +} + +for_each_non_boot_cpu() { + cpus=$(ls $CPU_PATH | grep "cpu[1-9].*") + for cpu in $cpus; do + $@ $cpu + done +} + +# Prints warning for all CPUs with missing cpufreq directory +print_unmanaged_cpus() +{ + for_each_cpu cpu_has_cpufreq_directory +} + +# Counts CPUs with cpufreq directories +count_cpufreq_managed_cpus() +{ + count=0; + + for cpu in `ls $CPU_PATH | grep "cpu[0-9].*"`; do + if [ -d /sys/devices/system/cpu/$cpu/cpufreq ]; then + let count=count+1; + fi + done + + echo $count; +} diff --git a/cpufreq.sh b/cpufreq.sh new file mode 100755 index 0000000..2bb3f4e --- /dev/null +++ b/cpufreq.sh @@ -0,0 +1,194 @@ +#!/bin/bash + +source cpu.sh + +# GLOBALS +CPU_PATH="/sys/devices/system/cpu" +GLOBAL_CPUFREQ="/sys/devices/system/cpu/cpufreq" + + +# GENERIC HELPERS +# $1: cpu +cpu_has_cpufreq_directory() +{ + if [ ! -d /sys/devices/system/cpu/$1/cpufreq ]; then + echo "Warning: No cpufreq directory present for $1" + fi +} + + +# READ CPUFREQ FILES + +# $1: directory path +__read_cpufreq_files() +{ + local filepath=$1 + + # Exit if cpu isn't mananged by cpufreq core + if [ ! -d $filepath ]; then + return; + fi + + local files=`ls $filepath` + + echo "Printing directory: $filepath" + echo "" + + for file in $files; do + if [ -f $filepath/$file ]; then + echo "$file:" + cat $filepath/$file + else + echo "" + __read_cpufreq_files "$filepath/$file" + fi + done + + echo "" +} + +# $1: directory path +# $2: cpu +read_cpufreq_files_for_cpu() +{ + local filepath=$CPU_PATH/$2/$1 + + __read_cpufreq_files $filepath +} + +read_all_cpufreq_files() +{ + echo "** Test: Running ${FUNCNAME[0]} **" + echo "" + + __read_cpufreq_files $GLOBAL_CPUFREQ + echo "" + + for_each_cpu read_cpufreq_files_for_cpu "cpufreq" + echo "------------------------------------------------" + echo "" +} + + +# UPDATE CPUFREQ FILES + +# $1: directory path +__update_cpufreq_files() +{ + local filepath=$1 + + # Exit if cpu isn't mananged by cpufreq core + if [ ! -d $filepath ]; then + return; + fi + + local files=`ls $filepath` + + echo "Updating directory: $filepath" + echo "" + + for file in $files; do + if [ -f $filepath/$file ]; then + # file is writable ? + local wfile=$(ls -l $filepath/$file | awk '$1 ~ /^.*w.*/ { print $NF; }') + if [ ! -z $wfile ]; then + local val=$(cat $filepath/$file) + echo "Writing $val to: $file" + echo $val > $filepath/$file + fi + else + echo "" + __update_cpufreq_files "$filepath/$file" + fi + done + + echo "" +} + +# $1: directory path +# $2: cpu +update_cpufreq_files_for_cpu() +{ + local filepath=$CPU_PATH/$2/$1 + + __update_cpufreq_files $filepath +} + +# Update all writable files with their existing values +update_all_cpufreq_files() +{ + echo "** Test: Running ${FUNCNAME[0]} **" + echo "" + + __update_cpufreq_files $GLOBAL_CPUFREQ + echo "" + + for_each_cpu update_cpufreq_files_for_cpu "cpufreq" + echo "------------------------------------------------" + echo "" +} + + +# CHANGE CPU FREQUENCIES + +# $1: cpu +# $2: frequency +set_cpu_frequency() +{ + echo $2 > $CPU_PATH/$1/cpufreq/scaling_setspeed +} + +# $1: cpu +test_all_cpu_frequencies() +{ + local filepath="$CPU_PATH/$1/cpufreq" + + # Exit if cpu isn't mananged by cpufreq core + if [ ! -d $filepath ]; then + return; + fi + + local found=$(switch_governor $1 "userspace") + if [ $found = 1 ]; then + echo "${FUNCNAME[0]}: userspace governor not available for: $1" + return; + else + echo "Switching governor for $1 to userspace" + fi + + local freqs=$(cat $filepath/scaling_available_frequencies) + echo "Available frequencies for $1: $freqs" + + # Set all frequencies one-by-one + for freq in $freqs; do + set_cpu_frequency $1 $freq + done +} + +# $1: loop count +shuffle_frequency_for_all_cpus() +{ + echo "** Test: Running ${FUNCNAME[0]} for $1 loops **" + echo "" + + for i in `seq 1 $1`; do + for_each_cpu test_all_cpu_frequencies + done + echo "------------------------------------------------" + echo "" +} + +# Calls the routine $1 passed to it and dumps all messages in: +# - script output: $2.txt +# - cpufreq messages: $2.cpufreq.txt +# - complete dmesg: $2.full.txt +call_routine() +{ + # call routine + $1 > $2.txt + + dmesg | grep cpufreq > $2.cpufreq.txt + + # We may need the full logs as well + dmesg --read-clear > $2.full.txt +} diff --git a/governor.sh b/governor.sh new file mode 100755 index 0000000..1c56426 --- /dev/null +++ b/governor.sh @@ -0,0 +1,86 @@ +#!/bin/bash +# +# Test governors + +source cpu.sh +source cpufreq.sh + +# Find governor's directory path +# $1: cpu, $2: governor +find_gov_directory() +{ + if [ -d $GLOBAL_CPUFREQ -a -d $GLOBAL_CPUFREQ/$2 ]; then + echo "$GLOBAL_CPUFREQ/$2" + elif [ -d $CPU_PATH/$1/cpufreq -a -d $CPU_PATH/$1/cpufreq/$2 ]; then + echo "$CPU_PATH/$1/cpufreq/$2" + fi +} + +# SWITCH GOVERNORS + +# param: +# $1: cpu, $2: governor +__switch_governor() +{ + echo $2 > $CPU_PATH/$1/cpufreq/scaling_governor +} + +# $1: cpu, $2: governor +switch_governor() +{ + local filepath=$CPU_PATH/$1/cpufreq/scaling_available_governors + + # check if governor is available + local found=$(cat $filepath | grep $2 | wc -l) + if [ $found = 0 ]; then + echo 1; + return + fi + + __switch_governor $1 $2 + echo 0; +} + +# $1: cpu, $2: governor +switch_show_governor() +{ + # switch governor + __switch_governor $1 $2 + + # show governor files + local govpath=$(find_gov_directory $1 $2) + + if [ ! -z $govpath ]; then + __read_cpufreq_files $govpath + fi +} + +# $1: function to be called, $2: cpu +call_for_each_governor() { + local filepath=$CPU_PATH/$2/cpufreq/scaling_available_governors + + # Exit if cpu isn't mananged by cpufreq core + if [ ! -f $filepath ]; then + return; + fi + + local governors=$(cat $filepath) + echo "Available governors for $2: $governors" + + for governor in $governors; do + $1 $2 $governor + done +} + +# $1: loop count +shuffle_governors_for_all_cpus() +{ + echo "** Test: Running ${FUNCNAME[0]} for $1 loops **" + echo "" + + for i in `seq 1 $1`; do + for_each_cpu call_for_each_governor switch_show_governor + done + echo "------------------------------------------------" + echo "" +} diff --git a/runme.sh b/runme.sh new file mode 100755 index 0000000..b4889a6 --- /dev/null +++ b/runme.sh @@ -0,0 +1,51 @@ +#!/bin/bash + +# parameters: +# - $1: Name of the output file with all the logs, dump.txt by default. + +source cpu.sh +source governor.sh +source special-tests.sh + +OUTFILE=${1-dump} + +cpufreq_test() +{ + echo "*** RUNNING CPUFREQ SANITY TESTS ***" + echo "====================================" + echo "" + + count=$(count_cpufreq_managed_cpus) + if [ $count = 0 ]; then + echo "No cpu is managed by cpufreq core, exiting" + exit; + else + echo "CPUFreq manages: $count CPUs" + echo "" + fi + + # Detect & print which CPUs aren't managed by cpufreq + print_unmanaged_cpus + + # read/update all cpufreq files + read_all_cpufreq_files + update_all_cpufreq_files + + # hotplug cpus + hotplug_1_by_1 5 + hotplug_together 5 + + # Test all governors + shuffle_governors_for_all_cpus 1 + + # Test all frequencies + shuffle_frequency_for_all_cpus 2 +} + +# Check validity of arguments +if [ "$1" = "-h" -o "$1" = "--help" ]; then + echo "Usage: $0 " + exit +fi + +call_routine cpufreq_test $OUTFILE diff --git a/special-tests.sh b/special-tests.sh new file mode 100755 index 0000000..b29f644 --- /dev/null +++ b/special-tests.sh @@ -0,0 +1,60 @@ +#!/bin/bash +# +# Special test cases reported by people + +# Testcase 1: Reported here: http://marc.info/?l=linux-pm&m=140618592709858&w=2 + +source cpu.sh +source cpufreq.sh +source governor.sh + +quick_shuffle_test1() +{ + # this is called concurrently from governor_race_test + for I in `seq 1000` + do + echo ondemand | sudo tee /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor & + echo userspace | sudo tee /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor & + done +} + +governor_race_test() +{ + echo "** Test: Running ${FUNCNAME[0]} **" + echo "" + + # run 8 concurrent instances + for I in `seq 8` + do + quick_shuffle_test1 & + done +} + +# $1: cpu +__simple_lockdep() +{ + # switch to ondemand + __switch_governor $1 "ondemand" + + # cat ondemand files + local ondir=$(find_gov_directory $1 "ondemand") + if [ -z $ondir ]; then + echo "${FUNCNAME[0]}Ondemand directory not created, quit" + return + fi + + cat $ondir/* + + # switch to conservative + __switch_governor $1 "conservative" +} + +simple_lockdep() +{ + echo "** Test: Running ${FUNCNAME[0]} **" + echo "" + + for_each_cpu __simple_lockdep +} +simple_lockdep +governor_race_test -- cgit v1.2.3