xref: /linux/tools/testing/selftests/liveupdate/vmtest.sh (revision 7b24dd46a70e94d8db83b50a04d46690fac216d0)
189dd1421SPasha Tatashin#!/bin/bash
289dd1421SPasha Tatashin# SPDX-License-Identifier: GPL-2.0
389dd1421SPasha Tatashin
489dd1421SPasha Tatashinset -ue
589dd1421SPasha Tatashin
689dd1421SPasha TatashinCROSS_COMPILE="${CROSS_COMPILE:-""}"
789dd1421SPasha Tatashin
889dd1421SPasha Tatashintest_dir=$(realpath "$(dirname "$0")")
989dd1421SPasha Tatashinkernel_dir=$(realpath "$test_dir/../../../..")
1089dd1421SPasha Tatashin
1189dd1421SPasha Tatashinworkspace_dir=""
1289dd1421SPasha Tatashinheaders_dir=""
1389dd1421SPasha Tatashininitrd=""
1489dd1421SPasha TatashinKEEP_WORKSPACE=0
1589dd1421SPasha Tatashin
1689dd1421SPasha Tatashinsource "$test_dir/../kselftest/ktap_helpers.sh"
1789dd1421SPasha Tatashin
1889dd1421SPasha Tatashinfunction get_arch_conf() {
1989dd1421SPasha Tatashin	local arch=$1
2089dd1421SPasha Tatashin	if [[ "$arch" == "arm64" ]]; then
2189dd1421SPasha Tatashin		QEMU_CMD="qemu-system-aarch64 -M virt -cpu max"
2289dd1421SPasha Tatashin		KERNEL_IMAGE="Image"
2389dd1421SPasha Tatashin		KERNEL_CMDLINE="console=ttyAMA0"
2489dd1421SPasha Tatashin	elif [[ "$arch" == "x86" ]]; then
2589dd1421SPasha Tatashin		QEMU_CMD="qemu-system-x86_64"
2689dd1421SPasha Tatashin		KERNEL_IMAGE="bzImage"
2789dd1421SPasha Tatashin		KERNEL_CMDLINE="console=ttyS0"
2889dd1421SPasha Tatashin	else
2989dd1421SPasha Tatashin		echo "Unsupported architecture: $arch"
3089dd1421SPasha Tatashin		exit 1
3189dd1421SPasha Tatashin	fi
3289dd1421SPasha Tatashin}
3389dd1421SPasha Tatashin
3489dd1421SPasha Tatashinfunction usage() {
3589dd1421SPasha Tatashin	cat <<EOF
3689dd1421SPasha Tatashin$0 [-d build_dir] [-j jobs] [-t target_arch] [-T test_name] [-w workspace_dir] [-k] [-h]
3789dd1421SPasha TatashinOptions:
3889dd1421SPasha Tatashin	-d)	path to the kernel build directory (default: .luo_test_build.<arch>)
3989dd1421SPasha Tatashin	-j)	number of jobs for compilation
4089dd1421SPasha Tatashin	-t)	run test for target_arch (aarch64, x86_64)
4189dd1421SPasha Tatashin	-T)	test name to run (default: luo_kexec_simple)
4289dd1421SPasha Tatashin	-w)	custom workspace directory (default: creates temp dir)
4389dd1421SPasha Tatashin	-k)	keep workspace directory after successful test
4489dd1421SPasha Tatashin	-h)	display this help
4589dd1421SPasha TatashinEOF
4689dd1421SPasha Tatashin}
4789dd1421SPasha Tatashin
4889dd1421SPasha Tatashinfunction cleanup() {
4989dd1421SPasha Tatashin	if [ "$KEEP_WORKSPACE" -eq 1 ]; then
5089dd1421SPasha Tatashin		echo "# Workspace preserved at: $workspace_dir"
5189dd1421SPasha Tatashin	else
5289dd1421SPasha Tatashin		rm -fr "$workspace_dir"
5389dd1421SPasha Tatashin	fi
5489dd1421SPasha Tatashin
5589dd1421SPasha Tatashin	ktap_finished
5689dd1421SPasha Tatashin}
5789dd1421SPasha Tatashin
5889dd1421SPasha Tatashinfunction skip() {
5989dd1421SPasha Tatashin	local msg=${1:-""}
6089dd1421SPasha Tatashin	ktap_test_skip "$msg"
6189dd1421SPasha Tatashin	exit "$KSFT_SKIP"
6289dd1421SPasha Tatashin}
6389dd1421SPasha Tatashin
6489dd1421SPasha Tatashinfunction fail() {
6589dd1421SPasha Tatashin	local msg=${1:-""}
6689dd1421SPasha Tatashin	ktap_test_fail "$msg"
6789dd1421SPasha Tatashin	exit "$KSFT_FAIL"
6889dd1421SPasha Tatashin}
6989dd1421SPasha Tatashin
7089dd1421SPasha Tatashinfunction detect_cross_compile() {
7189dd1421SPasha Tatashin	local target=$1
7289dd1421SPasha Tatashin	local host=$(uname -m)
7389dd1421SPasha Tatashin
7489dd1421SPasha Tatashin	[[ "$host" == "arm64" ]] && host="aarch64"
7589dd1421SPasha Tatashin	[[ "$target" == "arm64" ]] && target="aarch64"
7689dd1421SPasha Tatashin
7789dd1421SPasha Tatashin	if [[ "$host" == "$target" ]]; then
7889dd1421SPasha Tatashin		CROSS_COMPILE=""
7989dd1421SPasha Tatashin		return
8089dd1421SPasha Tatashin	fi
8189dd1421SPasha Tatashin
8289dd1421SPasha Tatashin	if [[ -n "$CROSS_COMPILE" ]]; then
8389dd1421SPasha Tatashin		return
8489dd1421SPasha Tatashin	fi
8589dd1421SPasha Tatashin
8689dd1421SPasha Tatashin	local candidate=""
8789dd1421SPasha Tatashin	case "$target" in
8889dd1421SPasha Tatashin		aarch64) candidate="aarch64-linux-gnu-" ;;
8989dd1421SPasha Tatashin		x86_64)  candidate="x86_64-linux-gnu-" ;;
9089dd1421SPasha Tatashin		*)       skip "Auto-detection for target '$target' not supported. Please set CROSS_COMPILE manually." ;;
9189dd1421SPasha Tatashin	esac
9289dd1421SPasha Tatashin
9389dd1421SPasha Tatashin	if command -v "${candidate}gcc" &> /dev/null; then
9489dd1421SPasha Tatashin		CROSS_COMPILE="$candidate"
9589dd1421SPasha Tatashin	else
9689dd1421SPasha Tatashin		skip "Compiler '${candidate}gcc' not found. Please install it (e.g., 'apt install gcc-aarch64-linux-gnu') or set CROSS_COMPILE."
9789dd1421SPasha Tatashin	fi
9889dd1421SPasha Tatashin}
9989dd1421SPasha Tatashin
10089dd1421SPasha Tatashinfunction build_kernel() {
10189dd1421SPasha Tatashin	local build_dir=$1
10289dd1421SPasha Tatashin	local make_cmd=$2
10389dd1421SPasha Tatashin	local kimage=$3
10489dd1421SPasha Tatashin	local target_arch=$4
10589dd1421SPasha Tatashin
10689dd1421SPasha Tatashin	local luo_config="$build_dir/luo.config"
10789dd1421SPasha Tatashin	local kconfig="$build_dir/.config"
10889dd1421SPasha Tatashin	local common_conf="$test_dir/config"
10989dd1421SPasha Tatashin	local arch_conf="$test_dir/config.$target_arch"
11089dd1421SPasha Tatashin
11189dd1421SPasha Tatashin	echo "# Building kernel in: $build_dir"
11289dd1421SPasha Tatashin
11389dd1421SPasha Tatashin	cat "$arch_conf" "$common_conf" | tee "$kconfig" > "$luo_config"
11489dd1421SPasha Tatashin	$make_cmd olddefconfig
11589dd1421SPasha Tatashin
11689dd1421SPasha Tatashin	# verify that kernel confiration has all necessary options
11789dd1421SPasha Tatashin	while read -r opt ; do
11889dd1421SPasha Tatashin		grep "$opt" "$kconfig" &>/dev/null || skip "$opt is missing"
11989dd1421SPasha Tatashin	done < "$luo_config"
12089dd1421SPasha Tatashin
12189dd1421SPasha Tatashin	$make_cmd "$kimage"
12289dd1421SPasha Tatashin	$make_cmd headers_install INSTALL_HDR_PATH="$headers_dir"
12389dd1421SPasha Tatashin}
12489dd1421SPasha Tatashin
12589dd1421SPasha Tatashinfunction mkinitrd() {
12689dd1421SPasha Tatashin	local build_dir=$1
12789dd1421SPasha Tatashin	local kernel_path=$2
12889dd1421SPasha Tatashin	local test_name=$3
12989dd1421SPasha Tatashin
13089dd1421SPasha Tatashin	# Compile the test binary and the init process
13189dd1421SPasha Tatashin	"$CROSS_COMPILE"gcc -static -O2 -nostdinc -nostdlib \
13289dd1421SPasha Tatashin		-I "$headers_dir/include" \
13389dd1421SPasha Tatashin		-I "$kernel_dir/tools/include/nolibc" \
134*df1a0d06SVipin Sharma		-I "$test_dir/lib/include" \
13589dd1421SPasha Tatashin		-o "$workspace_dir/test_binary" \
136*df1a0d06SVipin Sharma		"$test_dir/$test_name.c" "$test_dir/lib/lu_utils.c"
13789dd1421SPasha Tatashin
13889dd1421SPasha Tatashin	"$CROSS_COMPILE"gcc -s -static -Os -nostdinc -nostdlib		\
13989dd1421SPasha Tatashin			-fno-asynchronous-unwind-tables -fno-ident	\
14089dd1421SPasha Tatashin			-fno-stack-protector				\
14189dd1421SPasha Tatashin			-I "$headers_dir/include"			\
14289dd1421SPasha Tatashin			-I "$kernel_dir/tools/include/nolibc"		\
14389dd1421SPasha Tatashin			-o "$workspace_dir/init" "$test_dir/init.c"
14489dd1421SPasha Tatashin
14589dd1421SPasha Tatashin	cat > "$workspace_dir/cpio_list_inner" <<EOF
14689dd1421SPasha Tatashindir /dev 0755 0 0
14789dd1421SPasha Tatashindir /proc 0755 0 0
14889dd1421SPasha Tatashindir /debugfs 0755 0 0
14989dd1421SPasha Tatashinnod /dev/console 0600 0 0 c 5 1
15089dd1421SPasha Tatashinfile /init $workspace_dir/init 0755 0 0
15189dd1421SPasha Tatashinfile /test_binary $workspace_dir/test_binary 0755 0 0
15289dd1421SPasha TatashinEOF
15389dd1421SPasha Tatashin
15489dd1421SPasha Tatashin	# Generate inner_initrd.cpio
15589dd1421SPasha Tatashin	"$build_dir/usr/gen_init_cpio" "$workspace_dir/cpio_list_inner" > "$workspace_dir/inner_initrd.cpio"
15689dd1421SPasha Tatashin
15789dd1421SPasha Tatashin	cat > "$workspace_dir/cpio_list" <<EOF
15889dd1421SPasha Tatashindir /dev 0755 0 0
15989dd1421SPasha Tatashindir /proc 0755 0 0
16089dd1421SPasha Tatashindir /debugfs 0755 0 0
16189dd1421SPasha Tatashinnod /dev/console 0600 0 0 c 5 1
16289dd1421SPasha Tatashinfile /init $workspace_dir/init 0755 0 0
16389dd1421SPasha Tatashinfile /kernel $kernel_path 0644 0 0
16489dd1421SPasha Tatashinfile /test_binary $workspace_dir/test_binary 0755 0 0
16589dd1421SPasha Tatashinfile /initrd.img $workspace_dir/inner_initrd.cpio 0644 0 0
16689dd1421SPasha TatashinEOF
16789dd1421SPasha Tatashin
16889dd1421SPasha Tatashin	# Generate the final initrd
16989dd1421SPasha Tatashin	"$build_dir/usr/gen_init_cpio" "$workspace_dir/cpio_list" > "$initrd"
17089dd1421SPasha Tatashin}
17189dd1421SPasha Tatashin
17289dd1421SPasha Tatashinfunction run_qemu() {
17389dd1421SPasha Tatashin	local qemu_cmd=$1
17489dd1421SPasha Tatashin	local cmdline=$2
17589dd1421SPasha Tatashin	local kernel_path=$3
17689dd1421SPasha Tatashin	local serial="$workspace_dir/qemu.serial"
17789dd1421SPasha Tatashin
17889dd1421SPasha Tatashin	cmdline="$cmdline liveupdate=on panic=-1"
17989dd1421SPasha Tatashin
18089dd1421SPasha Tatashin	echo "# Serial Log: $serial"
18189dd1421SPasha Tatashin	timeout 30s \
18289dd1421SPasha Tatashin	$qemu_cmd -m 1G -smp 2 -no-reboot -nographic -nodefaults \
18389dd1421SPasha Tatashin		  -accel tcg -accel hvf -accel kvm \
18489dd1421SPasha Tatashin		  -serial file:"$serial" \
18589dd1421SPasha Tatashin		  -append "$cmdline" \
18689dd1421SPasha Tatashin		  -kernel "$kernel_path" \
18789dd1421SPasha Tatashin		  -initrd "$initrd"
18889dd1421SPasha Tatashin
18989dd1421SPasha Tatashin	grep "TEST PASSED" "$serial" &> /dev/null || fail "Liveupdate failed"
19089dd1421SPasha Tatashin}
19189dd1421SPasha Tatashin
19289dd1421SPasha Tatashinfunction target_to_arch() {
19389dd1421SPasha Tatashin	local target=$1
19489dd1421SPasha Tatashin	case $target in
19589dd1421SPasha Tatashin	     aarch64) echo "arm64" ;;
19689dd1421SPasha Tatashin	     x86_64) echo "x86" ;;
19789dd1421SPasha Tatashin	     *) skip "architecture $target is not supported"
19889dd1421SPasha Tatashin	esac
19989dd1421SPasha Tatashin}
20089dd1421SPasha Tatashin
20189dd1421SPasha Tatashinfunction main() {
20289dd1421SPasha Tatashin	local build_dir=""
20389dd1421SPasha Tatashin	local jobs=$(nproc)
20489dd1421SPasha Tatashin	local target="$(uname -m)"
20589dd1421SPasha Tatashin	local test_name="luo_kexec_simple"
20689dd1421SPasha Tatashin	local workspace_arg=""
20789dd1421SPasha Tatashin
20889dd1421SPasha Tatashin	set -o errtrace
20989dd1421SPasha Tatashin	trap fail ERR
21089dd1421SPasha Tatashin
21189dd1421SPasha Tatashin	while getopts 'hd:j:t:T:w:k' opt; do
21289dd1421SPasha Tatashin		case $opt in
21389dd1421SPasha Tatashin		d) build_dir="$OPTARG" ;;
21489dd1421SPasha Tatashin		j) jobs="$OPTARG" ;;
21589dd1421SPasha Tatashin		t) target="$OPTARG" ;;
21689dd1421SPasha Tatashin		T) test_name="$OPTARG" ;;
21789dd1421SPasha Tatashin		w) workspace_arg="$OPTARG" ;;
21889dd1421SPasha Tatashin		k) KEEP_WORKSPACE=1 ;;
21989dd1421SPasha Tatashin		h) usage; exit 0 ;;
22089dd1421SPasha Tatashin		*) echo "Unknown argument $opt"; usage; exit 1 ;;
22189dd1421SPasha Tatashin		esac
22289dd1421SPasha Tatashin	done
22389dd1421SPasha Tatashin
22489dd1421SPasha Tatashin	ktap_print_header
22589dd1421SPasha Tatashin	ktap_set_plan 1
22689dd1421SPasha Tatashin	trap cleanup EXIT
22789dd1421SPasha Tatashin
22889dd1421SPasha Tatashin	if [ -n "$workspace_arg" ]; then
22989dd1421SPasha Tatashin		workspace_dir="$(realpath -m "$workspace_arg")"
23089dd1421SPasha Tatashin		mkdir -p "$workspace_dir"
23189dd1421SPasha Tatashin	else
23289dd1421SPasha Tatashin		workspace_dir=$(mktemp -d /tmp/luo-test.XXXXXXXX)
23389dd1421SPasha Tatashin	fi
23489dd1421SPasha Tatashin
23589dd1421SPasha Tatashin	echo "# Workspace created at: $workspace_dir"
23689dd1421SPasha Tatashin	headers_dir="$workspace_dir/usr"
23789dd1421SPasha Tatashin	initrd="$workspace_dir/initrd.cpio"
23889dd1421SPasha Tatashin
23989dd1421SPasha Tatashin	detect_cross_compile "$target"
24089dd1421SPasha Tatashin
24189dd1421SPasha Tatashin	local arch=$(target_to_arch "$target")
24289dd1421SPasha Tatashin
24389dd1421SPasha Tatashin	if [ -z "$build_dir" ]; then
24489dd1421SPasha Tatashin		build_dir="$kernel_dir/.luo_test_build.$arch"
24589dd1421SPasha Tatashin	fi
24689dd1421SPasha Tatashin
24789dd1421SPasha Tatashin	mkdir -p "$build_dir"
24889dd1421SPasha Tatashin	build_dir=$(realpath "$build_dir")
24989dd1421SPasha Tatashin	get_arch_conf "$arch"
25089dd1421SPasha Tatashin
25189dd1421SPasha Tatashin	local make_cmd="make -s ARCH=$arch CROSS_COMPILE=$CROSS_COMPILE -j$jobs"
25289dd1421SPasha Tatashin	local make_cmd_build="$make_cmd -C $kernel_dir O=$build_dir"
25389dd1421SPasha Tatashin
25489dd1421SPasha Tatashin	build_kernel "$build_dir" "$make_cmd_build" "$KERNEL_IMAGE" "$target"
25589dd1421SPasha Tatashin
25689dd1421SPasha Tatashin	local final_kernel="$build_dir/arch/$arch/boot/$KERNEL_IMAGE"
25789dd1421SPasha Tatashin	mkinitrd "$build_dir" "$final_kernel" "$test_name"
25889dd1421SPasha Tatashin
25989dd1421SPasha Tatashin	run_qemu "$QEMU_CMD" "$KERNEL_CMDLINE" "$final_kernel"
26089dd1421SPasha Tatashin	ktap_test_pass "$test_name succeeded"
26189dd1421SPasha Tatashin}
26289dd1421SPasha Tatashin
26389dd1421SPasha Tatashinmain "$@"
264