xref: /linux/tools/testing/selftests/kho/vmtest.sh (revision bba2c3615bd6cfee7456d1130f2e6b01b3f4e9ba)
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_KEXEC_HANDOVER_DEBUG=y
63CONFIG_KEXEC_HANDOVER_DEBUGFS=y
64CONFIG_TEST_KEXEC_HANDOVER=y
65CONFIG_DEBUG_KERNEL=y
66CONFIG_DEBUG_VM=y
67CONFIG_DEBUG_VM_PGFLAGS=y
68CONFIG_SMP=y
69CONFIG_DEFERRED_STRUCT_PAGE_INIT=y
70$arch_kconfig
71EOF
72
73	make_cmd="$make_cmd -C $kernel_dir O=$build_dir"
74	$make_cmd olddefconfig
75
76	# verify that kernel confiration has all necessary options
77	while read -r opt ; do
78		grep "$opt" "$kconfig" &>/dev/null || skip "$opt is missing"
79	done < "$kho_config"
80
81	$make_cmd "$kimage"
82	$make_cmd headers_install INSTALL_HDR_PATH="$headers_dir"
83}
84
85function mkinitrd() {
86	local kernel=$1
87
88	"$CROSS_COMPILE"gcc -s -static -Os -nostdinc -nostdlib \
89			-fno-asynchronous-unwind-tables -fno-ident \
90			-I "$headers_dir/include" \
91			-I "$kernel_dir/tools/include/nolibc" \
92			-o "$tmp_dir/init" "$test_dir/init.c"
93
94	cat > "$tmp_dir/cpio_list" <<EOF
95dir /dev 0755 0 0
96dir /proc 0755 0 0
97dir /debugfs 0755 0 0
98nod /dev/console 0600 0 0 c 5 1
99file /init $tmp_dir/init 0755 0 0
100file /kernel $kernel 0644 0 0
101EOF
102
103	"$build_dir/usr/gen_init_cpio" "$tmp_dir/cpio_list" > "$initrd"
104}
105
106function run_qemu() {
107	local qemu_cmd=$1
108	local cmdline=$2
109	local kernel=$3
110	local serial="$tmp_dir/qemu.serial"
111
112	cmdline="$cmdline kho=on panic=-1"
113
114	$qemu_cmd -m 1G -smp 2 -no-reboot -nographic -nodefaults \
115		  -accel kvm -accel hvf -accel tcg  \
116		  -serial file:"$serial" \
117		  -append "$cmdline" \
118		  -kernel "$kernel" \
119		  -initrd "$initrd"
120
121	grep "KHO restore succeeded" "$serial" &> /dev/null || fail "KHO failed"
122}
123
124function target_to_arch() {
125	local target=$1
126
127	case $target in
128	     aarch64) echo "arm64" ;;
129	     x86_64) echo "x86" ;;
130	     *) skip "architecture $target is not supported"
131	esac
132}
133
134function main() {
135	local build_dir="$kernel_dir/.kho"
136	local jobs=$(($(nproc) * 2))
137	local target="$(uname -m)"
138
139	# skip the test if any of the preparation steps fails
140	set -o errtrace
141	trap skip ERR
142
143	while getopts 'hd:j:t:' opt; do
144		case $opt in
145		d)
146			build_dir="$OPTARG"
147			;;
148		j)
149		        jobs="$OPTARG"
150			;;
151		t)
152			target="$OPTARG"
153			;;
154		h)
155			usage
156			exit 0
157			;;
158		*)
159			echo Unknown argument "$opt"
160			usage
161			exit 1
162			;;
163		esac
164	done
165
166	ktap_print_header
167	ktap_set_plan 1
168
169	if [[ "$target" != "$(uname -m)" ]] && [[ -z "$CROSS_COMPILE" ]]; then
170		skip "Cross-platform testing needs to specify CROSS_COMPILE"
171	fi
172
173	mkdir -p "$build_dir"
174	local arch=$(target_to_arch "$target")
175	source "$test_dir/$arch.conf"
176
177	# build the kernel and create initrd
178	# initrd includes the kernel image that will be kexec'ed
179	local make_cmd="make ARCH=$arch CROSS_COMPILE=$CROSS_COMPILE -j$jobs"
180	build_kernel "$build_dir" "$make_cmd" "$QEMU_KCONFIG" "$KERNEL_IMAGE"
181
182	local kernel="$build_dir/arch/$arch/boot/$KERNEL_IMAGE"
183	mkinitrd "$kernel"
184
185	run_qemu "$QEMU_CMD" "$KERNEL_CMDLINE" "$kernel"
186
187	ktap_test_pass "KHO succeeded"
188}
189
190main "$@"
191