xref: /linux/tools/testing/selftests/bpf/vmtest.sh (revision 0a91336e287ca2557fead5221d2c79e0effd034e)
1c9709f52SKP Singh#!/bin/bash
2c9709f52SKP Singh# SPDX-License-Identifier: GPL-2.0
3c9709f52SKP Singh
4c9709f52SKP Singhset -e
5c9709f52SKP Singh
62294073dSPu Lehui# This script currently only works for the following platforms,
72294073dSPu Lehui# as it is based on the VM image used by the BPF CI, which is
82294073dSPu Lehui# available only for these architectures. We can also specify
92294073dSPu Lehui# the local rootfs image generated by the following script:
102294073dSPu Lehui# https://github.com/libbpf/ci/blob/main/rootfs/mkrootfs_debian.sh
11d95d5651SPu LehuiPLATFORM="${PLATFORM:-$(uname -m)}"
12d95d5651SPu Lehuicase "${PLATFORM}" in
1329ad850aSIlya Leoshkevichs390x)
1429ad850aSIlya Leoshkevich	QEMU_BINARY=qemu-system-s390x
1529ad850aSIlya Leoshkevich	QEMU_CONSOLE="ttyS1"
16d95d5651SPu Lehui	HOST_FLAGS=(-smp 2 -enable-kvm)
17d95d5651SPu Lehui	CROSS_FLAGS=(-smp 2)
18af320fb7SIlya Leoshkevich	BZIMAGE="arch/s390/boot/vmlinux"
19d95d5651SPu Lehui	ARCH="s390"
2029ad850aSIlya Leoshkevich	;;
2129ad850aSIlya Leoshkevichx86_64)
2229ad850aSIlya Leoshkevich	QEMU_BINARY=qemu-system-x86_64
2329ad850aSIlya Leoshkevich	QEMU_CONSOLE="ttyS0,115200"
24d95d5651SPu Lehui	HOST_FLAGS=(-cpu host -enable-kvm -smp 8)
25d95d5651SPu Lehui	CROSS_FLAGS=(-smp 8)
2629ad850aSIlya Leoshkevich	BZIMAGE="arch/x86/boot/bzImage"
27d95d5651SPu Lehui	ARCH="x86"
2829ad850aSIlya Leoshkevich	;;
2920776b72SManu Bretelleaarch64)
3020776b72SManu Bretelle	QEMU_BINARY=qemu-system-aarch64
3120776b72SManu Bretelle	QEMU_CONSOLE="ttyAMA0,115200"
32d95d5651SPu Lehui	HOST_FLAGS=(-M virt,gic-version=3 -cpu host -enable-kvm -smp 8)
33d95d5651SPu Lehui	CROSS_FLAGS=(-M virt,gic-version=3 -cpu cortex-a76 -smp 8)
3420776b72SManu Bretelle	BZIMAGE="arch/arm64/boot/Image"
35d95d5651SPu Lehui	ARCH="arm64"
3620776b72SManu Bretelle	;;
37b2bc9d50SPu Lehuiriscv64)
38b2bc9d50SPu Lehui	# required qemu version v7.2.0+
39b2bc9d50SPu Lehui	QEMU_BINARY=qemu-system-riscv64
40b2bc9d50SPu Lehui	QEMU_CONSOLE="ttyS0,115200"
41b2bc9d50SPu Lehui	HOST_FLAGS=(-M virt -cpu host -enable-kvm -smp 8)
42b2bc9d50SPu Lehui	CROSS_FLAGS=(-M virt -cpu rv64,sscofpmf=true -smp 8)
43b2bc9d50SPu Lehui	BZIMAGE="arch/riscv/boot/Image"
44b2bc9d50SPu Lehui	ARCH="riscv"
45b2bc9d50SPu Lehui	;;
46*3ce7cddeSLuis Gerhorstppc64el)
47*3ce7cddeSLuis Gerhorst	QEMU_BINARY=qemu-system-ppc64
48*3ce7cddeSLuis Gerhorst	QEMU_CONSOLE="hvc0"
49*3ce7cddeSLuis Gerhorst	# KVM could not be tested for powerpc, therefore not enabled for now.
50*3ce7cddeSLuis Gerhorst	HOST_FLAGS=(-machine pseries -cpu POWER9)
51*3ce7cddeSLuis Gerhorst	CROSS_FLAGS=(-machine pseries -cpu POWER9)
52*3ce7cddeSLuis Gerhorst	BZIMAGE="vmlinux"
53*3ce7cddeSLuis Gerhorst	ARCH="powerpc"
54*3ce7cddeSLuis Gerhorst	;;
5529ad850aSIlya Leoshkevich*)
5629ad850aSIlya Leoshkevich	echo "Unsupported architecture"
5729ad850aSIlya Leoshkevich	exit 1
5829ad850aSIlya Leoshkevich	;;
5929ad850aSIlya Leoshkevichesac
60c9709f52SKP SinghDEFAULT_COMMAND="./test_progs"
61c9709f52SKP SinghMOUNT_DIR="mnt"
622294073dSPu LehuiLOCAL_ROOTFS_IMAGE=""
63c9709f52SKP SinghROOTFS_IMAGE="root.img"
64c9709f52SKP SinghOUTPUT_DIR="$HOME/.bpf_selftests"
65b0cf0dcdSManu BretelleKCONFIG_REL_PATHS=("tools/testing/selftests/bpf/config"
66b0cf0dcdSManu Bretelle	"tools/testing/selftests/bpf/config.vm"
67d95d5651SPu Lehui	"tools/testing/selftests/bpf/config.${PLATFORM}")
68426b87b1SPu LehuiINDEX_URL="https://raw.githubusercontent.com/libbpf/ci/master/INDEX"
69c9709f52SKP SinghNUM_COMPILE_JOBS="$(nproc)"
7028544366SKP SinghLOG_FILE_BASE="$(date +"bpf_selftests.%Y-%m-%d_%H-%M-%S")"
7128544366SKP SinghLOG_FILE="${LOG_FILE_BASE}.log"
7228544366SKP SinghEXIT_STATUS_FILE="${LOG_FILE_BASE}.exit_status"
73c9709f52SKP Singh
74c9709f52SKP Singhusage()
75c9709f52SKP Singh{
76c9709f52SKP Singh	cat <<EOF
7763f8af0fSKP SinghUsage: $0 [-i] [-s] [-d <output_dir>] -- [<command>]
78c9709f52SKP Singh
79c9709f52SKP Singh<command> is the command you would normally run when you are in
80c9709f52SKP Singhtools/testing/selftests/bpf. e.g:
81c9709f52SKP Singh
82c9709f52SKP Singh	$0 -- ./test_progs -t test_lsm
83c9709f52SKP Singh
8463f8af0fSKP SinghIf no command is specified and a debug shell (-s) is not requested,
8563f8af0fSKP Singh"${DEFAULT_COMMAND}" will be run by default.
86c9709f52SKP Singh
87d95d5651SPu LehuiUsing PLATFORM= and CROSS_COMPILE= options will enable cross platform testing:
88d95d5651SPu Lehui
89d95d5651SPu Lehui  PLATFORM=<platform> CROSS_COMPILE=<toolchain> $0 -- ./test_progs -t test_lsm
90d95d5651SPu Lehui
91c9709f52SKP SinghIf you build your kernel using KBUILD_OUTPUT= or O= options, these
92c9709f52SKP Singhcan be passed as environment variables to the script:
93c9709f52SKP Singh
94c9709f52SKP Singh  O=<kernel_build_path> $0 -- ./test_progs -t test_lsm
95c9709f52SKP Singh
96c9709f52SKP Singhor
97c9709f52SKP Singh
98c9709f52SKP Singh  KBUILD_OUTPUT=<kernel_build_path> $0 -- ./test_progs -t test_lsm
99c9709f52SKP Singh
100c9709f52SKP SinghOptions:
101c9709f52SKP Singh
1022294073dSPu Lehui	-l)             Specify the path to the local rootfs image.
103c9709f52SKP Singh	-i)		Update the rootfs image with a newer version.
104c9709f52SKP Singh	-d)		Update the output directory (default: ${OUTPUT_DIR})
105c9709f52SKP Singh	-j)		Number of jobs for compilation, similar to -j in make
106c9709f52SKP Singh			(default: ${NUM_COMPILE_JOBS})
10763f8af0fSKP Singh	-s)		Instead of powering off the VM, start an interactive
10863f8af0fSKP Singh			shell. If <command> is specified, the shell runs after
10963f8af0fSKP Singh			the command finishes executing
110c9709f52SKP SinghEOF
111c9709f52SKP Singh}
112c9709f52SKP Singh
113c9709f52SKP Singhunset URLS
114c9709f52SKP Singhpopulate_url_map()
115c9709f52SKP Singh{
116c9709f52SKP Singh	if ! declare -p URLS &> /dev/null; then
117c9709f52SKP Singh		# URLS contain the mapping from file names to URLs where
118c9709f52SKP Singh		# those files can be downloaded from.
119c9709f52SKP Singh		declare -gA URLS
120c9709f52SKP Singh		while IFS=$'\t' read -r name url; do
121c9709f52SKP Singh			URLS["$name"]="$url"
122c9709f52SKP Singh		done < <(curl -Lsf ${INDEX_URL})
123c9709f52SKP Singh	fi
124c9709f52SKP Singh}
125c9709f52SKP Singh
126c9709f52SKP Singhnewest_rootfs_version()
127c9709f52SKP Singh{
128c9709f52SKP Singh	{
129c9709f52SKP Singh	for file in "${!URLS[@]}"; do
130d95d5651SPu Lehui		if [[ $file =~ ^"${PLATFORM}"/libbpf-vmtest-rootfs-(.*)\.tar\.zst$ ]]; then
131c9709f52SKP Singh			echo "${BASH_REMATCH[1]}"
132c9709f52SKP Singh		fi
133c9709f52SKP Singh	done
134c9709f52SKP Singh	} | sort -rV | head -1
135c9709f52SKP Singh}
136c9709f52SKP Singh
137c9709f52SKP Singhdownload_rootfs()
138c9709f52SKP Singh{
1390c3fc330SPu Lehui	populate_url_map
1400c3fc330SPu Lehui
1410c3fc330SPu Lehui	local rootfsversion="$(newest_rootfs_version)"
142d95d5651SPu Lehui	local file="${PLATFORM}/libbpf-vmtest-rootfs-$rootfsversion.tar.zst"
1430c3fc330SPu Lehui
1440c3fc330SPu Lehui	if [[ ! -v URLS[$file] ]]; then
1450c3fc330SPu Lehui		echo "$file not found" >&2
1460c3fc330SPu Lehui		return 1
1470c3fc330SPu Lehui	fi
1480c3fc330SPu Lehui
1490c3fc330SPu Lehui	echo "Downloading $file..." >&2
1500c3fc330SPu Lehui	curl -Lsf "${URLS[$file]}" "${@:2}"
1510c3fc330SPu Lehui}
1520c3fc330SPu Lehui
1530c3fc330SPu Lehuiload_rootfs()
1540c3fc330SPu Lehui{
1550c3fc330SPu Lehui	local dir="$1"
156c9709f52SKP Singh
157c9709f52SKP Singh	if ! which zstd &> /dev/null; then
158c9709f52SKP Singh		echo 'Could not find "zstd" on the system, please install zstd'
159c9709f52SKP Singh		exit 1
160c9709f52SKP Singh	fi
161c9709f52SKP Singh
1622294073dSPu Lehui	if [[ -n "${LOCAL_ROOTFS_IMAGE}" ]]; then
1632294073dSPu Lehui		cat "${LOCAL_ROOTFS_IMAGE}" | zstd -d | sudo tar -C "$dir" -x
1642294073dSPu Lehui	else
1650c3fc330SPu Lehui		download_rootfs | zstd -d | sudo tar -C "$dir" -x
1662294073dSPu Lehui	fi
167c9709f52SKP Singh}
168c9709f52SKP Singh
169c9709f52SKP Singhrecompile_kernel()
170c9709f52SKP Singh{
171c9709f52SKP Singh	local kernel_checkout="$1"
172c9709f52SKP Singh	local make_command="$2"
173c9709f52SKP Singh
174c9709f52SKP Singh	cd "${kernel_checkout}"
175c9709f52SKP Singh
176c9709f52SKP Singh	${make_command} olddefconfig
177c9709f52SKP Singh	${make_command}
178c9709f52SKP Singh}
179c9709f52SKP Singh
180c9709f52SKP Singhmount_image()
181c9709f52SKP Singh{
182c9709f52SKP Singh	local rootfs_img="${OUTPUT_DIR}/${ROOTFS_IMAGE}"
183c9709f52SKP Singh	local mount_dir="${OUTPUT_DIR}/${MOUNT_DIR}"
184c9709f52SKP Singh
185c9709f52SKP Singh	sudo mount -o loop "${rootfs_img}" "${mount_dir}"
186c9709f52SKP Singh}
187c9709f52SKP Singh
188c9709f52SKP Singhunmount_image()
189c9709f52SKP Singh{
190c9709f52SKP Singh	local mount_dir="${OUTPUT_DIR}/${MOUNT_DIR}"
191c9709f52SKP Singh
192c9709f52SKP Singh	sudo umount "${mount_dir}" &> /dev/null
193c9709f52SKP Singh}
194c9709f52SKP Singh
195c9709f52SKP Singhupdate_selftests()
196c9709f52SKP Singh{
197c9709f52SKP Singh	local kernel_checkout="$1"
198c9709f52SKP Singh	local selftests_dir="${kernel_checkout}/tools/testing/selftests/bpf"
199c9709f52SKP Singh
200c9709f52SKP Singh	cd "${selftests_dir}"
201c9709f52SKP Singh	${make_command}
202c9709f52SKP Singh
203c9709f52SKP Singh	# Mount the image and copy the selftests to the image.
204c9709f52SKP Singh	mount_image
205c9709f52SKP Singh	sudo rm -rf "${mount_dir}/root/bpf"
206c9709f52SKP Singh	sudo cp -r "${selftests_dir}" "${mount_dir}/root"
207c9709f52SKP Singh	unmount_image
208c9709f52SKP Singh}
209c9709f52SKP Singh
210c9709f52SKP Singhupdate_init_script()
211c9709f52SKP Singh{
212c9709f52SKP Singh	local init_script_dir="${OUTPUT_DIR}/${MOUNT_DIR}/etc/rcS.d"
213c9709f52SKP Singh	local init_script="${init_script_dir}/S50-startup"
214c9709f52SKP Singh	local command="$1"
21563f8af0fSKP Singh	local exit_command="$2"
216c9709f52SKP Singh
217c9709f52SKP Singh	mount_image
218c9709f52SKP Singh
219c9709f52SKP Singh	if [[ ! -d "${init_script_dir}" ]]; then
220c9709f52SKP Singh		cat <<EOF
221c9709f52SKP SinghCould not find ${init_script_dir} in the mounted image.
222c9709f52SKP SinghThis likely indicates a bad rootfs image, Please download
223c9709f52SKP Singha new image by passing "-i" to the script
224c9709f52SKP SinghEOF
225c9709f52SKP Singh		exit 1
226c9709f52SKP Singh
227c9709f52SKP Singh	fi
228c9709f52SKP Singh
22963f8af0fSKP Singh	sudo bash -c "echo '#!/bin/bash' > ${init_script}"
230c9709f52SKP Singh
23163f8af0fSKP Singh	if [[ "${command}" != "" ]]; then
23263f8af0fSKP Singh		sudo bash -c "cat >>${init_script}" <<EOF
23328544366SKP Singh# Have a default value in the exit status file
23428544366SKP Singh# incase the VM is forcefully stopped.
23528544366SKP Singhecho "130" > "/root/${EXIT_STATUS_FILE}"
23628544366SKP Singh
237c9709f52SKP Singh{
238c9709f52SKP Singh	cd /root/bpf
239c9709f52SKP Singh	echo ${command}
240c9709f52SKP Singh	stdbuf -oL -eL ${command}
24128544366SKP Singh	echo "\$?" > "/root/${EXIT_STATUS_FILE}"
24228544366SKP Singh} 2>&1 | tee "/root/${LOG_FILE}"
24363f8af0fSKP Singh# Ensure that the logs are written to disk
24463f8af0fSKP Singhsync
245c9709f52SKP SinghEOF
24663f8af0fSKP Singh	fi
247c9709f52SKP Singh
24863f8af0fSKP Singh	sudo bash -c "echo ${exit_command} >> ${init_script}"
249c9709f52SKP Singh	sudo chmod a+x "${init_script}"
250c9709f52SKP Singh	unmount_image
251c9709f52SKP Singh}
252c9709f52SKP Singh
253c9709f52SKP Singhcreate_vm_image()
254c9709f52SKP Singh{
255c9709f52SKP Singh	local rootfs_img="${OUTPUT_DIR}/${ROOTFS_IMAGE}"
256c9709f52SKP Singh	local mount_dir="${OUTPUT_DIR}/${MOUNT_DIR}"
257c9709f52SKP Singh
258c9709f52SKP Singh	rm -rf "${rootfs_img}"
259c9709f52SKP Singh	touch "${rootfs_img}"
260c9709f52SKP Singh	chattr +C "${rootfs_img}" >/dev/null 2>&1 || true
261c9709f52SKP Singh
262c9709f52SKP Singh	truncate -s 2G "${rootfs_img}"
263c9709f52SKP Singh	mkfs.ext4 -q "${rootfs_img}"
264c9709f52SKP Singh
265c9709f52SKP Singh	mount_image
2660c3fc330SPu Lehui	load_rootfs "${mount_dir}"
267c9709f52SKP Singh	unmount_image
268c9709f52SKP Singh}
269c9709f52SKP Singh
270c9709f52SKP Singhrun_vm()
271c9709f52SKP Singh{
272c9709f52SKP Singh	local kernel_bzimage="$1"
273c9709f52SKP Singh	local rootfs_img="${OUTPUT_DIR}/${ROOTFS_IMAGE}"
274c9709f52SKP Singh
275c9709f52SKP Singh	if ! which "${QEMU_BINARY}" &> /dev/null; then
276c9709f52SKP Singh		cat <<EOF
277c9709f52SKP SinghCould not find ${QEMU_BINARY}
278c9709f52SKP SinghPlease install qemu or set the QEMU_BINARY environment variable.
279c9709f52SKP SinghEOF
280c9709f52SKP Singh		exit 1
281c9709f52SKP Singh	fi
282c9709f52SKP Singh
283d95d5651SPu Lehui	if [[ "${PLATFORM}" != "$(uname -m)" ]]; then
284d95d5651SPu Lehui		QEMU_FLAGS=("${CROSS_FLAGS[@]}")
285d95d5651SPu Lehui	else
286d95d5651SPu Lehui		QEMU_FLAGS=("${HOST_FLAGS[@]}")
287d95d5651SPu Lehui	fi
288d95d5651SPu Lehui
289c9709f52SKP Singh	${QEMU_BINARY} \
290c9709f52SKP Singh		-nodefaults \
291c9709f52SKP Singh		-display none \
292c9709f52SKP Singh		-serial mon:stdio \
293b38101c5SYucong Sun		"${QEMU_FLAGS[@]}" \
294547208a3SYucong Sun		-m 4G \
295c9709f52SKP Singh		-drive file="${rootfs_img}",format=raw,index=1,media=disk,if=virtio,cache=none \
296c9709f52SKP Singh		-kernel "${kernel_bzimage}" \
29729ad850aSIlya Leoshkevich		-append "root=/dev/vda rw console=${QEMU_CONSOLE}"
298c9709f52SKP Singh}
299c9709f52SKP Singh
300c9709f52SKP Singhcopy_logs()
301c9709f52SKP Singh{
302c9709f52SKP Singh	local mount_dir="${OUTPUT_DIR}/${MOUNT_DIR}"
30328544366SKP Singh	local log_file="${mount_dir}/root/${LOG_FILE}"
30428544366SKP Singh	local exit_status_file="${mount_dir}/root/${EXIT_STATUS_FILE}"
305c9709f52SKP Singh
306c9709f52SKP Singh	mount_image
307c9709f52SKP Singh	sudo cp ${log_file} "${OUTPUT_DIR}"
30828544366SKP Singh	sudo cp ${exit_status_file} "${OUTPUT_DIR}"
309c9709f52SKP Singh	sudo rm -f ${log_file}
310c9709f52SKP Singh	unmount_image
311c9709f52SKP Singh}
312c9709f52SKP Singh
313c9709f52SKP Singhis_rel_path()
314c9709f52SKP Singh{
315c9709f52SKP Singh	local path="$1"
316c9709f52SKP Singh
317c9709f52SKP Singh	[[ ${path:0:1} != "/" ]]
318c9709f52SKP Singh}
319c9709f52SKP Singh
32040b09653SDaniel Müllerdo_update_kconfig()
32140b09653SDaniel Müller{
32240b09653SDaniel Müller	local kernel_checkout="$1"
32340b09653SDaniel Müller	local kconfig_file="$2"
32440b09653SDaniel Müller
32540b09653SDaniel Müller	rm -f "$kconfig_file" 2> /dev/null
32640b09653SDaniel Müller
32740b09653SDaniel Müller	for config in "${KCONFIG_REL_PATHS[@]}"; do
32840b09653SDaniel Müller		local kconfig_src="${kernel_checkout}/${config}"
32940b09653SDaniel Müller		cat "$kconfig_src" >> "$kconfig_file"
33040b09653SDaniel Müller	done
33140b09653SDaniel Müller}
33240b09653SDaniel Müller
333c9709f52SKP Singhupdate_kconfig()
334c9709f52SKP Singh{
33540b09653SDaniel Müller	local kernel_checkout="$1"
33640b09653SDaniel Müller	local kconfig_file="$2"
337c9709f52SKP Singh
33840b09653SDaniel Müller	if [[ -f "${kconfig_file}" ]]; then
33940b09653SDaniel Müller		local local_modified="$(stat -c %Y "${kconfig_file}")"
34040b09653SDaniel Müller
34140b09653SDaniel Müller		for config in "${KCONFIG_REL_PATHS[@]}"; do
34240b09653SDaniel Müller			local kconfig_src="${kernel_checkout}/${config}"
34340b09653SDaniel Müller			local src_modified="$(stat -c %Y "${kconfig_src}")"
34440b09653SDaniel Müller			# Only update the config if it has been updated after the
34540b09653SDaniel Müller			# previously cached config was created. This avoids
34640b09653SDaniel Müller			# unnecessarily compiling the kernel and selftests.
34740b09653SDaniel Müller			if [[ "${src_modified}" -gt "${local_modified}" ]]; then
34840b09653SDaniel Müller				do_update_kconfig "$kernel_checkout" "$kconfig_file"
34940b09653SDaniel Müller				# Once we have found one outdated configuration
35040b09653SDaniel Müller				# there is no need to check other ones.
35140b09653SDaniel Müller				break
352c9709f52SKP Singh			fi
35340b09653SDaniel Müller		done
354c9709f52SKP Singh	else
35540b09653SDaniel Müller		do_update_kconfig "$kernel_checkout" "$kconfig_file"
356c9709f52SKP Singh	fi
357c9709f52SKP Singh}
358c9709f52SKP Singh
359d020b236SDaniel Xucatch()
360d020b236SDaniel Xu{
361d020b236SDaniel Xu	local exit_code=$1
362d020b236SDaniel Xu	local exit_status_file="${OUTPUT_DIR}/${EXIT_STATUS_FILE}"
363d020b236SDaniel Xu	# This is just a cleanup and the directory may
364d020b236SDaniel Xu	# have already been unmounted. So, don't let this
365d020b236SDaniel Xu	# clobber the error code we intend to return.
366d020b236SDaniel Xu	unmount_image || true
367d020b236SDaniel Xu	if [[ -f "${exit_status_file}" ]]; then
368d020b236SDaniel Xu		exit_code="$(cat ${exit_status_file})"
369d020b236SDaniel Xu	fi
370d020b236SDaniel Xu	exit ${exit_code}
371d020b236SDaniel Xu}
372d020b236SDaniel Xu
373c9709f52SKP Singhmain()
374c9709f52SKP Singh{
375c9709f52SKP Singh	local script_dir="$(cd -P -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd -P)"
376c9709f52SKP Singh	local kernel_checkout=$(realpath "${script_dir}"/../../../../)
377c9709f52SKP Singh	# By default the script searches for the kernel in the checkout directory but
378c9709f52SKP Singh	# it also obeys environment variables O= and KBUILD_OUTPUT=
37929ad850aSIlya Leoshkevich	local kernel_bzimage="${kernel_checkout}/${BZIMAGE}"
380c9709f52SKP Singh	local command="${DEFAULT_COMMAND}"
381c9709f52SKP Singh	local update_image="no"
38263f8af0fSKP Singh	local exit_command="poweroff -f"
38363f8af0fSKP Singh	local debug_shell="no"
384c9709f52SKP Singh
3852294073dSPu Lehui	while getopts ':hskl:id:j:' opt; do
386c9709f52SKP Singh		case ${opt} in
3872294073dSPu Lehui		l)
3882294073dSPu Lehui			LOCAL_ROOTFS_IMAGE="$OPTARG"
3892294073dSPu Lehui			;;
390c9709f52SKP Singh		i)
391c9709f52SKP Singh			update_image="yes"
392c9709f52SKP Singh			;;
393c9709f52SKP Singh		d)
394c9709f52SKP Singh			OUTPUT_DIR="$OPTARG"
395c9709f52SKP Singh			;;
396c9709f52SKP Singh		j)
397c9709f52SKP Singh			NUM_COMPILE_JOBS="$OPTARG"
398c9709f52SKP Singh			;;
39963f8af0fSKP Singh		s)
40063f8af0fSKP Singh			command=""
40163f8af0fSKP Singh			debug_shell="yes"
40263f8af0fSKP Singh			exit_command="bash"
40363f8af0fSKP Singh			;;
404c9709f52SKP Singh		h)
405c9709f52SKP Singh			usage
406c9709f52SKP Singh			exit 0
407c9709f52SKP Singh			;;
408c9709f52SKP Singh		\? )
409c9709f52SKP Singh			echo "Invalid Option: -$OPTARG"
410c9709f52SKP Singh			usage
411c9709f52SKP Singh			exit 1
412c9709f52SKP Singh			;;
413c9709f52SKP Singh		: )
414c9709f52SKP Singh			echo "Invalid Option: -$OPTARG requires an argument"
415c9709f52SKP Singh			usage
416c9709f52SKP Singh			exit 1
417c9709f52SKP Singh			;;
418c9709f52SKP Singh		esac
419c9709f52SKP Singh	done
420c9709f52SKP Singh	shift $((OPTIND -1))
421c9709f52SKP Singh
422d020b236SDaniel Xu	trap 'catch "$?"' EXIT
423d020b236SDaniel Xu
424d95d5651SPu Lehui	if [[ "${PLATFORM}" != "$(uname -m)" ]] && [[ -z "${CROSS_COMPILE}" ]]; then
425d95d5651SPu Lehui		echo "Cross-platform testing needs to specify CROSS_COMPILE"
426d95d5651SPu Lehui		exit 1
427d95d5651SPu Lehui	fi
428d95d5651SPu Lehui
42963f8af0fSKP Singh	if [[ $# -eq 0  && "${debug_shell}" == "no" ]]; then
430c9709f52SKP Singh		echo "No command specified, will run ${DEFAULT_COMMAND} in the vm"
431c9709f52SKP Singh	else
432c9709f52SKP Singh		command="$@"
433c9709f52SKP Singh	fi
434c9709f52SKP Singh
435c9709f52SKP Singh	local kconfig_file="${OUTPUT_DIR}/latest.config"
436d95d5651SPu Lehui	local make_command="make ARCH=${ARCH} CROSS_COMPILE=${CROSS_COMPILE} \
437d95d5651SPu Lehui			    -j ${NUM_COMPILE_JOBS} KCONFIG_CONFIG=${kconfig_file}"
438c9709f52SKP Singh
439c9709f52SKP Singh	# Figure out where the kernel is being built.
440c9709f52SKP Singh	# O takes precedence over KBUILD_OUTPUT.
441c9709f52SKP Singh	if [[ "${O:=""}" != "" ]]; then
442c9709f52SKP Singh		if is_rel_path "${O}"; then
443c9709f52SKP Singh			O="$(realpath "${PWD}/${O}")"
444c9709f52SKP Singh		fi
44529ad850aSIlya Leoshkevich		kernel_bzimage="${O}/${BZIMAGE}"
446c9709f52SKP Singh		make_command="${make_command} O=${O}"
447c9709f52SKP Singh	elif [[ "${KBUILD_OUTPUT:=""}" != "" ]]; then
448c9709f52SKP Singh		if is_rel_path "${KBUILD_OUTPUT}"; then
449c9709f52SKP Singh			KBUILD_OUTPUT="$(realpath "${PWD}/${KBUILD_OUTPUT}")"
450c9709f52SKP Singh		fi
45129ad850aSIlya Leoshkevich		kernel_bzimage="${KBUILD_OUTPUT}/${BZIMAGE}"
452c9709f52SKP Singh		make_command="${make_command} KBUILD_OUTPUT=${KBUILD_OUTPUT}"
453c9709f52SKP Singh	fi
454c9709f52SKP Singh
455c9709f52SKP Singh	local rootfs_img="${OUTPUT_DIR}/${ROOTFS_IMAGE}"
456c9709f52SKP Singh	local mount_dir="${OUTPUT_DIR}/${MOUNT_DIR}"
457c9709f52SKP Singh
458c9709f52SKP Singh	echo "Output directory: ${OUTPUT_DIR}"
459c9709f52SKP Singh
460c9709f52SKP Singh	mkdir -p "${OUTPUT_DIR}"
461c9709f52SKP Singh	mkdir -p "${mount_dir}"
46240b09653SDaniel Müller	update_kconfig "${kernel_checkout}" "${kconfig_file}"
463c9709f52SKP Singh
464c9709f52SKP Singh	recompile_kernel "${kernel_checkout}" "${make_command}"
465c9709f52SKP Singh
466c9709f52SKP Singh	if [[ "${update_image}" == "no" && ! -f "${rootfs_img}" ]]; then
467c9709f52SKP Singh		echo "rootfs image not found in ${rootfs_img}"
468c9709f52SKP Singh		update_image="yes"
469c9709f52SKP Singh	fi
470c9709f52SKP Singh
471c9709f52SKP Singh	if [[ "${update_image}" == "yes" ]]; then
472c9709f52SKP Singh		create_vm_image
473c9709f52SKP Singh	fi
474c9709f52SKP Singh
475c9709f52SKP Singh	update_selftests "${kernel_checkout}" "${make_command}"
47663f8af0fSKP Singh	update_init_script "${command}" "${exit_command}"
477c9709f52SKP Singh	run_vm "${kernel_bzimage}"
47863f8af0fSKP Singh	if [[ "${command}" != "" ]]; then
47928544366SKP Singh		copy_logs
48028544366SKP Singh		echo "Logs saved in ${OUTPUT_DIR}/${LOG_FILE}"
48163f8af0fSKP Singh	fi
482c9709f52SKP Singh}
483c9709f52SKP Singh
484c9709f52SKP Singhmain "$@"
485