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