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