1# $NetBSD: t_cpuctl.sh,v 1.6 2021/04/12 01:18:13 mrg Exp $
2#
3# Copyright (c) 2020 The NetBSD Foundation, Inc.
4# All rights reserved.
5#
6# This code is derived from software contributed to The NetBSD Foundation
7# by Jukka Ruohonen.
8#
9# Redistribution and use in source and binary forms, with or without
10# modification, are permitted provided that the following conditions
11# are met:
12# 1. Redistributions of source code must retain the above copyright
13#    notice, this list of conditions and the following disclaimer.
14# 2. Redistributions in binary form must reproduce the above copyright
15#    notice, this list of conditions and the following disclaimer in the
16#    documentation and/or other materials provided with the distribution.
17#
18# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
19# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
20# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21# PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
22# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28# POSSIBILITY OF SUCH DAMAGE.
29#
30tmp="/tmp/cpuctl.txt"
31
32setcpu() {
33
34	ncpu=$(sysctl -n hw.ncpu)
35
36	if [ $ncpu -eq 1 ]; then
37		atf_pass
38	fi
39
40	while [ $ncpu -gt 1 ]; do
41
42		cpuid=$(( $ncpu - 1 ))
43		cpuctl $1 $cpuid >/dev/null 2>&1
44
45		if [ ! $? -eq 0 ]; then
46			$2 $3
47		fi
48
49		ncpu=$(( $ncpu - 1 ))
50	done
51
52	# Additional check that interrupts cannot be
53	# disabled for the primary CPU (PR kern/45117).
54	#
55	cpuctl nointr 0 >/dev/null 2>&1
56
57	if [ $? -eq 0 ]; then
58		$2 $3
59	fi
60}
61
62clean() {
63
64	i=0
65
66	while read line; do
67
68		i=$(( $i + 1 ))
69
70		if [ $i -lt 3 ]; then
71			continue
72		fi
73
74		cpuid=$(echo $line | awk '{print $1}')
75		online=$(echo $line | awk '{print $3}')
76		intr=$(echo $line | awk '{print $4}')
77
78		cpuctl $online $cpuid
79		cpuctl $intr $cpuid
80
81	done < $tmp
82
83	rm $tmp
84}
85
86# ncpu.
87#
88atf_test_case ncpu
89ncpu_head() {
90	atf_require_prog cpuctl
91	atf_set "descr" "Test that cpuctl(8) returns the " \
92			"same number of CPUs as sysctl(8)"
93}
94
95ncpu_body() {
96
97	lst=$(cpuctl list | wc -l)
98	ncpu=$(( $lst - 2 ))
99
100	if [ $ncpu -eq 1 ]; then
101		atf_pass
102	fi
103
104	if [ $(sysctl -n hw.ncpu) -eq $ncpu ]; then
105		atf_pass
106	fi
107
108	atf_fail "Different number of CPUs"
109}
110
111# err
112#
113atf_test_case err cleanup
114err_head() {
115	atf_require_prog cpuctl
116	atf_set "require.user" "root"
117	atf_set "descr" "Test invalid parameters to cpuctl(8)"
118}
119
120err_body() {
121
122	cpuctl list > $tmp
123	ncpu=$(sysctl -n hw.ncpu)
124
125	atf_check -s exit:1 -e ignore \
126		-o empty -x cpuctl identify -1
127
128	atf_check -s exit:1 -e ignore \
129		-o empty -x cpuctl offline -1
130
131	atf_check -s exit:1 -e ignore \
132		-o empty -x cpuctl nointr -1
133
134	atf_check -s exit:1 -e ignore \
135		-o empty -x cpuctl identify $(( $ncpu + 1 ))
136
137	atf_check -s exit:1 -e ignore \
138		  -o empty -x cpuctl offline $(( $ncpu + 1 ))
139
140	atf_check -s exit:1 -e ignore \
141		-o empty -x cpuctl nointr $(( $ncpu + 1 ))
142}
143
144err_cleanup() {
145	clean
146}
147
148# identify
149#
150atf_test_case identify
151identify_head() {
152	atf_require_prog cpuctl
153	atf_set "descr" "Test that cpuctl(8) identifies at least " \
154			"something without segfaulting (PR bin/54220)"
155}
156
157identify_body() {
158
159	ncpu=$(sysctl -n hw.ncpu)
160
161	while [ $ncpu -gt 0 ]; do
162		cpuid=$(( $ncpu - 1 ))
163		atf_check -s exit:0 -o not-empty -x cpuctl identify $cpuid
164		ncpu=$(( $ncpu - 1 ))
165	done
166
167	atf_pass
168}
169
170#
171# check_cpuctl_ok - only run some tests if
172# is set ATF_USR_SBIN_CPUCTL_OFFLINE_ENABLE.
173check_cpuctl_ok() {
174	if [ -z "$ATF_USR_SBIN_CPUCTL_OFFLINE_ENABLE" ]; then
175		return 1
176	fi
177	return 0
178}
179
180# offline
181#
182atf_test_case offline cleanup
183offline_head() {
184	atf_require_prog cpuctl
185	atf_set "require.user" "root"
186	atf_set "descr" "Test setting CPUs offline"
187}
188
189offline_body() {
190
191	if ! check_cpuctl_ok; then
192		atf_skip \
193		   "test sometimes hangs or upsets machine"
194	fi
195
196	cpuctl list > $tmp
197	setcpu "offline" atf_fail "error in setting a CPU offline"
198
199	# Additional check that the boot processor cannot be
200	# set offline, as noted in the cpuctl(8) manual page.
201	#
202	cpuctl offline 0 >/dev/null 2>&1
203
204	if [ $? -eq 0 ]; then
205		$2 $3
206	fi
207}
208
209offline_cleanup() {
210	clean
211}
212
213atf_test_case offline_perm
214offline_perm_head() {
215	atf_require_prog cpuctl
216	atf_set "require.user" "unprivileged"
217	atf_set "descr" "Test setting CPUs offline as a user"
218}
219
220offline_perm_body() {
221	setcpu "offline" atf_pass
222}
223
224# nointr
225#
226atf_test_case nointr cleanup
227nointr_head() {
228	atf_require_prog cpuctl
229	atf_set "require.user" "root"
230	atf_set "descr" "Test disabling interrupts for CPUs"
231}
232
233nointr_body() {
234
235	if ! check_cpuctl_ok; then
236		atf_skip \
237		   "test sometimes hangs or upsets machine"
238	fi
239
240	cpuctl list > $tmp
241	setcpu "nointr" atf_fail "error in disabling interrupts"
242}
243
244nointr_cleanup() {
245	clean
246}
247
248atf_test_case nointr_perm
249nointr_perm_head() {
250	atf_require_prog cpuctl
251	atf_set "require.user" "unprivileged"
252	atf_set "descr" "Test disabling interrupts as a user"
253}
254
255nointr_perm_body() {
256	setcpu "nointr" atf_pass
257}
258
259atf_init_test_cases() {
260	atf_add_test_case ncpu
261	atf_add_test_case err
262	atf_add_test_case identify
263	atf_add_test_case offline
264	atf_add_test_case offline_perm
265	atf_add_test_case nointr
266	atf_add_test_case nointr_perm
267}
268