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