xref: /linux/tools/testing/selftests/kho/vmtest.sh (revision b753522bed0b7e388a643f58d91bd81d8849ba43)
1#!/bin/bash
2# SPDX-License-Identifier: GPL-2.0
3
4set -ue
5
6CROSS_COMPILE="${CROSS_COMPILE:-""}"
7
8test_dir=$(realpath "$(dirname "$0")")
9kernel_dir=$(realpath "$test_dir/../../../..")
10
11tmp_dir=$(mktemp -d /tmp/kho-test.XXXXXXXX)
12headers_dir="$tmp_dir/usr"
13initrd_dir="$tmp_dir/initrd"
14initrd="$tmp_dir/initrd.cpio"
15
16source "$test_dir/../kselftest/ktap_helpers.sh"
17
18function usage() {
19	cat <<EOF
20$0 [-d build_dir] [-j jobs] [-t target_arch] [-h]
21Options:
22	-d)	path to the kernel build directory
23	-j)	number of jobs for compilation, similar to -j in make
24	-t)	run test for target_arch, requires CROSS_COMPILE set
25		supported targets: aarch64, x86_64
26	-h)	display this help
27EOF
28}
29
30function cleanup() {
31	rm -fr "$tmp_dir"
32	ktap_finished
33}
34trap cleanup EXIT
35
36function skip() {
37	local msg=${1:-""}
38
39	ktap_test_skip "$msg"
40	exit "$KSFT_SKIP"
41}
42
43function fail() {
44	local msg=${1:-""}
45
46	ktap_test_fail "$msg"
47	exit "$KSFT_FAIL"
48}
49
50function build_kernel() {
51	local build_dir=$1
52	local make_cmd=$2
53	local arch_kconfig=$3
54	local kimage=$4
55
56	local kho_config="$tmp_dir/kho.config"
57	local kconfig="$build_dir/.config"
58
59	# enable initrd, KHO and KHO test in kernel configuration
60	tee "$kconfig" > "$kho_config" <<EOF
61CONFIG_BLK_DEV_INITRD=y
62CONFIG_KEXEC_HANDOVER=y
63CONFIG_TEST_KEXEC_HANDOVER=y
64CONFIG_DEBUG_KERNEL=y
65CONFIG_DEBUG_VM=y
66$arch_kconfig
67EOF
68
69	make_cmd="$make_cmd -C $kernel_dir O=$build_dir"
70	$make_cmd olddefconfig
71
72	# verify that kernel confiration has all necessary options
73	while read -r opt ; do
74		grep "$opt" "$kconfig" &>/dev/null || skip "$opt is missing"
75	done < "$kho_config"
76
77	$make_cmd "$kimage"
78	$make_cmd headers_install INSTALL_HDR_PATH="$headers_dir"
79}
80
81function mkinitrd() {
82	local kernel=$1
83
84	mkdir -p "$initrd_dir"/{dev,debugfs,proc}
85	sudo mknod "$initrd_dir/dev/console" c 5 1
86
87	"$CROSS_COMPILE"gcc -s -static -Os -nostdinc -I"$headers_dir/include" \
88			-fno-asynchronous-unwind-tables -fno-ident -nostdlib \
89			-include "$test_dir/../../../include/nolibc/nolibc.h" \
90			-o "$initrd_dir/init" "$test_dir/init.c" \
91
92	cp "$kernel" "$initrd_dir/kernel"
93
94	pushd "$initrd_dir" &>/dev/null
95	find . | cpio -H newc --create > "$initrd" 2>/dev/null
96	popd &>/dev/null
97}
98
99function run_qemu() {
100	local qemu_cmd=$1
101	local cmdline=$2
102	local kernel=$3
103	local serial="$tmp_dir/qemu.serial"
104
105	cmdline="$cmdline kho=on panic=-1"
106
107	$qemu_cmd -m 1G -smp 2 -no-reboot -nographic -nodefaults \
108		  -accel kvm -accel hvf -accel tcg  \
109		  -serial file:"$serial" \
110		  -append "$cmdline" \
111		  -kernel "$kernel" \
112		  -initrd "$initrd"
113
114	grep "KHO restore succeeded" "$serial" &> /dev/null || fail "KHO failed"
115}
116
117function target_to_arch() {
118	local target=$1
119
120	case $target in
121	     aarch64) echo "arm64" ;;
122	     x86_64) echo "x86" ;;
123	     *) skip "architecture $target is not supported"
124	esac
125}
126
127function main() {
128	local build_dir="$kernel_dir/.kho"
129	local jobs=$(($(nproc) * 2))
130	local target="$(uname -m)"
131
132	# skip the test if any of the preparation steps fails
133	set -o errtrace
134	trap skip ERR
135
136	while getopts 'hd:j:t:' opt; do
137		case $opt in
138		d)
139			build_dir="$OPTARG"
140			;;
141		j)
142		        jobs="$OPTARG"
143			;;
144		t)
145			target="$OPTARG"
146			;;
147		h)
148			usage
149			exit 0
150			;;
151		*)
152			echo Unknown argument "$opt"
153			usage
154			exit 1
155			;;
156		esac
157	done
158
159	ktap_print_header
160	ktap_set_plan 1
161
162	if [[ "$target" != "$(uname -m)" ]] && [[ -z "$CROSS_COMPILE" ]]; then
163		skip "Cross-platform testing needs to specify CROSS_COMPILE"
164	fi
165
166	mkdir -p "$build_dir"
167	local arch=$(target_to_arch "$target")
168	source "$test_dir/$arch.conf"
169
170	# build the kernel and create initrd
171	# initrd includes the kernel image that will be kexec'ed
172	local make_cmd="make ARCH=$arch CROSS_COMPILE=$CROSS_COMPILE -j$jobs"
173	build_kernel "$build_dir" "$make_cmd" "$QEMU_KCONFIG" "$KERNEL_IMAGE"
174
175	local kernel="$build_dir/arch/$arch/boot/$KERNEL_IMAGE"
176	mkinitrd "$kernel"
177
178	run_qemu "$QEMU_CMD" "$KERNEL_CMDLINE" "$kernel"
179
180	ktap_test_pass "KHO succeeded"
181}
182
183main "$@"
184