1#!/bin/bash 2# SPDX-License-Identifier: GPL-2.0 3 4SYSFS= 5# Kselftest framework requirement - SKIP code is 4. 6ksft_skip=4 7 8prerequisite() 9{ 10 msg="skip all tests:" 11 12 if [ $UID != 0 ]; then 13 echo $msg must be run as root >&2 14 exit $ksft_skip 15 fi 16 17 taskset -p 01 $$ 18 19 SYSFS=`mount -t sysfs | head -1 | awk '{ print $3 }'` 20 21 if [ ! -d "$SYSFS" ]; then 22 echo $msg sysfs is not mounted >&2 23 exit $ksft_skip 24 fi 25 26 if ! ls $SYSFS/devices/system/cpu/cpu* > /dev/null 2>&1; then 27 echo $msg cpu hotplug is not supported >&2 28 exit $ksft_skip 29 fi 30 31 echo "CPU online/offline summary:" 32 online_cpus=`cat $SYSFS/devices/system/cpu/online` 33 online_max=${online_cpus##*-} 34 35 if [[ "$online_cpus" = "$online_max" ]]; then 36 echo "$msg: since there is only one cpu: $online_cpus" 37 exit $ksft_skip 38 fi 39 40 present_cpus=`cat $SYSFS/devices/system/cpu/present` 41 present_max=${present_cpus##*-} 42 echo "present_cpus = $present_cpus present_max = $present_max" 43 44 echo -e "\t Cpus in online state: $online_cpus" 45 46 offline_cpus=`cat $SYSFS/devices/system/cpu/offline` 47 if [[ "a$offline_cpus" = "a" ]]; then 48 offline_cpus=0 49 else 50 offline_max=${offline_cpus##*-} 51 fi 52 echo -e "\t Cpus in offline state: $offline_cpus" 53} 54 55# 56# list all hot-pluggable CPUs 57# 58hotpluggable_cpus() 59{ 60 local state=${1:-.\*} 61 62 for cpu in $SYSFS/devices/system/cpu/cpu*; do 63 if [ -f $cpu/online ] && grep -q $state $cpu/online; then 64 echo ${cpu##/*/cpu} 65 fi 66 done 67} 68 69hotplaggable_offline_cpus() 70{ 71 hotpluggable_cpus 0 72} 73 74hotpluggable_online_cpus() 75{ 76 hotpluggable_cpus 1 77} 78 79cpu_is_online() 80{ 81 grep -q 1 $SYSFS/devices/system/cpu/cpu$1/online 82} 83 84cpu_is_offline() 85{ 86 grep -q 0 $SYSFS/devices/system/cpu/cpu$1/online 87} 88 89online_cpu() 90{ 91 echo 1 > $SYSFS/devices/system/cpu/cpu$1/online 92} 93 94offline_cpu() 95{ 96 echo 0 > $SYSFS/devices/system/cpu/cpu$1/online 97} 98 99online_cpu_expect_success() 100{ 101 local cpu=$1 102 103 if ! online_cpu $cpu; then 104 echo $FUNCNAME $cpu: unexpected fail >&2 105 exit 1 106 elif ! cpu_is_online $cpu; then 107 echo $FUNCNAME $cpu: unexpected offline >&2 108 exit 1 109 fi 110} 111 112online_cpu_expect_fail() 113{ 114 local cpu=$1 115 116 if online_cpu $cpu 2> /dev/null; then 117 echo $FUNCNAME $cpu: unexpected success >&2 118 exit 1 119 elif ! cpu_is_offline $cpu; then 120 echo $FUNCNAME $cpu: unexpected online >&2 121 exit 1 122 fi 123} 124 125offline_cpu_expect_success() 126{ 127 local cpu=$1 128 129 if ! offline_cpu $cpu; then 130 echo $FUNCNAME $cpu: unexpected fail >&2 131 exit 1 132 elif ! cpu_is_offline $cpu; then 133 echo $FUNCNAME $cpu: unexpected offline >&2 134 exit 1 135 fi 136} 137 138offline_cpu_expect_fail() 139{ 140 local cpu=$1 141 142 if offline_cpu $cpu 2> /dev/null; then 143 echo $FUNCNAME $cpu: unexpected success >&2 144 exit 1 145 elif ! cpu_is_online $cpu; then 146 echo $FUNCNAME $cpu: unexpected offline >&2 147 exit 1 148 fi 149} 150 151error=-12 152allcpus=0 153priority=0 154online_cpus=0 155online_max=0 156offline_cpus=0 157offline_max=0 158present_cpus=0 159present_max=0 160 161while getopts e:ahp: opt; do 162 case $opt in 163 e) 164 error=$OPTARG 165 ;; 166 a) 167 allcpus=1 168 ;; 169 h) 170 echo "Usage $0 [ -a ] [ -e errno ] [ -p notifier-priority ]" 171 echo -e "\t default offline one cpu" 172 echo -e "\t run with -a option to offline all cpus" 173 exit 174 ;; 175 p) 176 priority=$OPTARG 177 ;; 178 esac 179done 180 181if ! [ "$error" -ge -4095 -a "$error" -lt 0 ]; then 182 echo "error code must be -4095 <= errno < 0" >&2 183 exit 1 184fi 185 186prerequisite 187 188# 189# Safe test (default) - offline and online one cpu 190# 191if [ $allcpus -eq 0 ]; then 192 echo "Limited scope test: one hotplug cpu" 193 echo -e "\t (leaves cpu in the original state):" 194 echo -e "\t online to offline to online: cpu $online_max" 195 offline_cpu_expect_success $online_max 196 online_cpu_expect_success $online_max 197 198 if [[ $offline_cpus -gt 0 ]]; then 199 echo -e "\t offline to online to offline: cpu $present_max" 200 online_cpu_expect_success $present_max 201 offline_cpu_expect_success $present_max 202 online_cpu $present_max 203 fi 204 exit 0 205else 206 echo "Full scope test: all hotplug cpus" 207 echo -e "\t online all offline cpus" 208 echo -e "\t offline all online cpus" 209 echo -e "\t online all offline cpus" 210fi 211 212# 213# Online all hot-pluggable CPUs 214# 215for cpu in `hotplaggable_offline_cpus`; do 216 online_cpu_expect_success $cpu 217done 218 219# 220# Offline all hot-pluggable CPUs 221# 222for cpu in `hotpluggable_online_cpus`; do 223 offline_cpu_expect_success $cpu 224done 225 226# 227# Online all hot-pluggable CPUs again 228# 229for cpu in `hotplaggable_offline_cpus`; do 230 online_cpu_expect_success $cpu 231done 232 233# 234# Test with cpu notifier error injection 235# 236 237DEBUGFS=`mount -t debugfs | head -1 | awk '{ print $3 }'` 238NOTIFIER_ERR_INJECT_DIR=$DEBUGFS/notifier-error-inject/cpu 239 240prerequisite_extra() 241{ 242 msg="skip extra tests:" 243 244 /sbin/modprobe -q -r cpu-notifier-error-inject 245 /sbin/modprobe -q cpu-notifier-error-inject priority=$priority 246 247 if [ ! -d "$DEBUGFS" ]; then 248 echo $msg debugfs is not mounted >&2 249 exit $ksft_skip 250 fi 251 252 if [ ! -d $NOTIFIER_ERR_INJECT_DIR ]; then 253 echo $msg cpu-notifier-error-inject module is not available >&2 254 exit $ksft_skip 255 fi 256} 257 258prerequisite_extra 259 260# 261# Offline all hot-pluggable CPUs 262# 263echo 0 > $NOTIFIER_ERR_INJECT_DIR/actions/CPU_DOWN_PREPARE/error 264for cpu in `hotpluggable_online_cpus`; do 265 offline_cpu_expect_success $cpu 266done 267 268# 269# Test CPU hot-add error handling (offline => online) 270# 271echo $error > $NOTIFIER_ERR_INJECT_DIR/actions/CPU_UP_PREPARE/error 272for cpu in `hotplaggable_offline_cpus`; do 273 online_cpu_expect_fail $cpu 274done 275 276# 277# Online all hot-pluggable CPUs 278# 279echo 0 > $NOTIFIER_ERR_INJECT_DIR/actions/CPU_UP_PREPARE/error 280for cpu in `hotplaggable_offline_cpus`; do 281 online_cpu_expect_success $cpu 282done 283 284# 285# Test CPU hot-remove error handling (online => offline) 286# 287echo $error > $NOTIFIER_ERR_INJECT_DIR/actions/CPU_DOWN_PREPARE/error 288for cpu in `hotpluggable_online_cpus`; do 289 offline_cpu_expect_fail $cpu 290done 291 292echo 0 > $NOTIFIER_ERR_INJECT_DIR/actions/CPU_DOWN_PREPARE/error 293/sbin/modprobe -q -r cpu-notifier-error-inject 294