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