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