xref: /kvm-unit-tests/scripts/vmm.bash (revision 61ff990187ed8d2f29b648609f1b4e5791366600)
1# The following parameters are enabled by default when running a test with
2# kvmtool:
3# --nodefaults: suppress VM configuration that cannot be disabled (like
4#               modifying the supplied kernel command line). Otherwise tests
5#               that use the command line will fail without this parameter.
6# --network mode=none: do not create a network device. kvmtool tries to help the
7#               user by automatically create one, and then prints a warning
8#               when the VM terminates if the device hasn't been initialized.
9# --loglevel=warning: reduce verbosity
10: "${KVMTOOL_DEFAULT_OPTS:="--nodefaults --network mode=none --loglevel=warning"}"
11
12##############################################################################
13# qemu_fixup_return_code translates the ambiguous exit status in Table1 to that
14# in Table2.  Table3 simply documents the complete status table.
15#
16# Table1: Before fixup
17# --------------------
18# 0      - Unexpected exit from QEMU (possible signal), or the unittest did
19#          not use debug-exit
20# 1      - most likely unittest succeeded, or QEMU failed
21#
22# Table2: After fixup
23# -------------------
24# 0      - Everything succeeded
25# 1      - most likely QEMU failed
26#
27# Table3: Complete table
28# ----------------------
29# 0      - SUCCESS
30# 1      - most likely QEMU failed
31# 2      - most likely a run script failed
32# 3      - most likely the unittest failed
33# 124    - most likely the unittest timed out
34# 127    - most likely the unittest called abort()
35# 1..127 - FAILURE (could be QEMU, a run script, or the unittest)
36# >= 128 - Signal (signum = status - 128)
37##############################################################################
38function qemu_fixup_return_code()
39{
40	local ret=$1
41	# Remove $ret from the list of arguments
42	shift 1
43	local errors=$*
44	local sig
45
46	[ $ret -eq 134 ] && echo "QEMU Aborted" >&2
47
48	if [ "$errors" ]; then
49		sig=$(grep 'terminating on signal' <<<"$errors")
50		if [ "$sig" ]; then
51			# This is too complex for ${var/search/replace}
52			# shellcheck disable=SC2001
53			sig=$(sed 's/.*terminating on signal \([0-9][0-9]*\).*/\1/' <<<"$sig")
54		fi
55	fi
56
57	if [ $ret -eq 0 ]; then
58		# Some signals result in a zero return status, but the
59		# error log tells the truth.
60		if [ "$sig" ]; then
61			((ret=sig+128))
62		else
63			# Exiting with zero (non-debugexit) is an error
64			ret=1
65		fi
66	elif [ $ret -eq 1 ]; then
67		# Even when ret==1 (unittest success) if we also got stderr
68		# logs, then we assume a QEMU failure. Otherwise we translate
69		# status of 1 to 0 (SUCCESS)
70	        if [ "$errors" ]; then
71			if ! grep -qvi warning <<<"$errors" ; then
72				ret=0
73			fi
74		else
75			ret=0
76		fi
77	fi
78
79	echo $ret
80}
81
82function qemu_parse_premature_failure()
83{
84	local log=$*
85
86	echo "$log" | grep "_NO_FILE_4Uhere_" |
87		grep -q -e "[Cc]ould not \(load\|open\) kernel" \
88			-e "error loading" \
89			-e "failed to load" &&
90		return 1
91	return 0
92}
93
94#
95# Probe for MAX_SMP, in case it's less than the number of host cpus.
96#
97function qemu_probe_maxsmp()
98{
99	local runtime_arch_run="$1"
100	local smp
101
102	if smp=$($runtime_arch_run _NO_FILE_4Uhere_ -smp $MAX_SMP |& grep 'SMP CPUs'); then
103		smp=${smp##* }
104		smp=${smp/\(}
105		smp=${smp/\)}
106		echo "Restricting MAX_SMP from ($MAX_SMP) to the max supported ($smp)" >&2
107		MAX_SMP=$smp
108	fi
109}
110
111function kvmtool_fixup_return_code()
112{
113	local ret=$1
114
115	# Force run_test_status() to interpret the STATUS line.
116	if [ $ret -eq 0 ]; then
117		ret=1
118	fi
119
120	echo $ret
121}
122
123function kvmtool_parse_premature_failure()
124{
125	local log=$*
126
127	echo "$log" | grep "Fatal: Unable to open kernel _NO_FILE_4Uhere_" &&
128		return 1
129	return 0
130}
131
132function kvmtool_probe_maxsmp()
133{
134	echo "kvmtool automatically limits the number of VCPUs to maximum supported"
135	echo "The 'smp' test parameter won't be modified"
136}
137
138declare -A vmm_optname=(
139	[qemu,args]='-append'
140	[qemu,default_opts]=''
141	[qemu,fixup_return_code]=qemu_fixup_return_code
142	[qemu,initrd]='-initrd'
143	[qemu,nr_cpus]='-smp'
144	[qemu,parse_premature_failure]=qemu_parse_premature_failure
145	[qemu,probe_maxsmp]=qemu_probe_maxsmp
146
147	[kvmtool,args]='--params'
148	[kvmtool,default_opts]="$KVMTOOL_DEFAULT_OPTS"
149	[kvmtool,fixup_return_code]=kvmtool_fixup_return_code
150	[kvmtool,initrd]='--initrd'
151	[kvmtool,nr_cpus]='--cpus'
152	[kvmtool,parse_premature_failure]=kvmtool_parse_premature_failure
153	[kvmtool,probe_maxsmp]=kvmtool_probe_maxsmp
154)
155
156function vmm_optname_args()
157{
158	echo ${vmm_optname[$(vmm_get_target),args]}
159}
160
161function vmm_default_opts()
162{
163	echo ${vmm_optname[$(vmm_get_target),default_opts]}
164}
165
166function vmm_fixup_return_code()
167{
168	${vmm_optname[$(vmm_get_target),fixup_return_code]} "$@"
169}
170
171function vmm_optname_initrd()
172{
173	echo ${vmm_optname[$(vmm_get_target),initrd]}
174}
175
176function vmm_optname_nr_cpus()
177{
178	echo ${vmm_optname[$(vmm_get_target),nr_cpus]}
179}
180
181function vmm_parse_premature_failure()
182{
183	${vmm_optname[$(vmm_get_target),parse_premature_failure]} "$@"
184}
185
186function vmm_probe_maxsmp()
187{
188	${vmm_optname[$(vmm_get_target),probe_maxsmp]} "$1"
189}
190
191function vmm_get_target()
192{
193	if [[ -z "$TARGET" ]]; then
194		echo "qemu"
195	else
196		echo "$TARGET"
197	fi
198}
199
200function vmm_check_supported()
201{
202	# We're not interested in the return code for vmm_get_target().
203	# shellcheck disable=SC2155
204	local target=$(vmm_get_target)
205
206	case "$target" in
207	qemu | kvmtool)
208		return 0
209		;;
210	*)
211		echo "$0 does not support target '$target'"
212		exit 2
213		;;
214	esac
215}
216
217function vmm_unittest_params_name()
218{
219	# shellcheck disable=SC2155
220	local target=$(vmm_get_target)
221
222	case "$target" in
223	qemu)
224		echo "extra_params|qemu_params"
225		;;
226	kvmtool)
227		echo "kvmtool_params"
228		;;
229	*)
230		echo "$0 does not support '$target'"
231		exit 2
232		;;
233	esac
234}
235