• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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