GNU Linux-libre 4.14.313-gnu1
[releases.git] / tools / testing / selftests / cpu-hotplug / cpu-on-off-test.sh
1 #!/bin/bash
2 # SPDX-License-Identifier: GPL-2.0
3
4 SYSFS=
5
6 prerequisite()
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 #
56 hotpluggable_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
67 hotplaggable_offline_cpus()
68 {
69         hotpluggable_cpus 0
70 }
71
72 hotpluggable_online_cpus()
73 {
74         hotpluggable_cpus 1
75 }
76
77 cpu_is_online()
78 {
79         grep -q 1 $SYSFS/devices/system/cpu/cpu$1/online
80 }
81
82 cpu_is_offline()
83 {
84         grep -q 0 $SYSFS/devices/system/cpu/cpu$1/online
85 }
86
87 online_cpu()
88 {
89         echo 1 > $SYSFS/devices/system/cpu/cpu$1/online
90 }
91
92 offline_cpu()
93 {
94         echo 0 > $SYSFS/devices/system/cpu/cpu$1/online
95 }
96
97 online_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
110 online_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
123 offline_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
136 offline_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
149 error=-12
150 allcpus=0
151 priority=0
152 online_cpus=0
153 online_max=0
154 offline_cpus=0
155 offline_max=0
156 present_cpus=0
157 present_max=0
158
159 while 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
177 done
178
179 if ! [ "$error" -ge -4095 -a "$error" -lt 0 ]; then
180         echo "error code must be -4095 <= errno < 0" >&2
181         exit 1
182 fi
183
184 prerequisite
185
186 #
187 # Safe test (default) - offline and online one cpu
188 #
189 if [ $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
203 else
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"
208 fi
209
210 #
211 # Online all hot-pluggable CPUs
212 #
213 for cpu in `hotplaggable_offline_cpus`; do
214         online_cpu_expect_success $cpu
215 done
216
217 #
218 # Offline all hot-pluggable CPUs
219 #
220 for cpu in `hotpluggable_online_cpus`; do
221         offline_cpu_expect_success $cpu
222 done
223
224 #
225 # Online all hot-pluggable CPUs again
226 #
227 for cpu in `hotplaggable_offline_cpus`; do
228         online_cpu_expect_success $cpu
229 done
230
231 #
232 # Test with cpu notifier error injection
233 #
234
235 DEBUGFS=`mount -t debugfs | head -1 | awk '{ print $3 }'`
236 NOTIFIER_ERR_INJECT_DIR=$DEBUGFS/notifier-error-inject/cpu
237
238 prerequisite_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
256 prerequisite_extra
257
258 #
259 # Offline all hot-pluggable CPUs
260 #
261 echo 0 > $NOTIFIER_ERR_INJECT_DIR/actions/CPU_DOWN_PREPARE/error
262 for cpu in `hotpluggable_online_cpus`; do
263         offline_cpu_expect_success $cpu
264 done
265
266 #
267 # Test CPU hot-add error handling (offline => online)
268 #
269 echo $error > $NOTIFIER_ERR_INJECT_DIR/actions/CPU_UP_PREPARE/error
270 for cpu in `hotplaggable_offline_cpus`; do
271         online_cpu_expect_fail $cpu
272 done
273
274 #
275 # Online all hot-pluggable CPUs
276 #
277 echo 0 > $NOTIFIER_ERR_INJECT_DIR/actions/CPU_UP_PREPARE/error
278 for cpu in `hotplaggable_offline_cpus`; do
279         online_cpu_expect_success $cpu
280 done
281
282 #
283 # Test CPU hot-remove error handling (online => offline)
284 #
285 echo $error > $NOTIFIER_ERR_INJECT_DIR/actions/CPU_DOWN_PREPARE/error
286 for cpu in `hotpluggable_online_cpus`; do
287         offline_cpu_expect_fail $cpu
288 done
289
290 echo 0 > $NOTIFIER_ERR_INJECT_DIR/actions/CPU_DOWN_PREPARE/error
291 /sbin/modprobe -q -r cpu-notifier-error-inject