linux/tools/testing/selftests/kho/vmtest.sh

184 lines
3.8 KiB
Bash
Raw Permalink Normal View History

#!/bin/bash
# SPDX-License-Identifier: GPL-2.0
set -ue
CROSS_COMPILE="${CROSS_COMPILE:-""}"
test_dir=$(realpath "$(dirname "$0")")
kernel_dir=$(realpath "$test_dir/../../../..")
tmp_dir=$(mktemp -d /tmp/kho-test.XXXXXXXX)
headers_dir="$tmp_dir/usr"
initrd_dir="$tmp_dir/initrd"
initrd="$tmp_dir/initrd.cpio"
source "$test_dir/../kselftest/ktap_helpers.sh"
function usage() {
cat <<EOF
$0 [-d build_dir] [-j jobs] [-t target_arch] [-h]
Options:
-d) path to the kernel build directory
-j) number of jobs for compilation, similar to -j in make
-t) run test for target_arch, requires CROSS_COMPILE set
supported targets: aarch64, x86_64
-h) display this help
EOF
}
function cleanup() {
rm -fr "$tmp_dir"
ktap_finished
}
trap cleanup EXIT
function skip() {
local msg=${1:-""}
ktap_test_skip "$msg"
exit "$KSFT_SKIP"
}
function fail() {
local msg=${1:-""}
ktap_test_fail "$msg"
exit "$KSFT_FAIL"
}
function build_kernel() {
local build_dir=$1
local make_cmd=$2
local arch_kconfig=$3
local kimage=$4
local kho_config="$tmp_dir/kho.config"
local kconfig="$build_dir/.config"
# enable initrd, KHO and KHO test in kernel configuration
tee "$kconfig" > "$kho_config" <<EOF
CONFIG_BLK_DEV_INITRD=y
CONFIG_KEXEC_HANDOVER=y
CONFIG_TEST_KEXEC_HANDOVER=y
CONFIG_DEBUG_KERNEL=y
CONFIG_DEBUG_VM=y
$arch_kconfig
EOF
make_cmd="$make_cmd -C $kernel_dir O=$build_dir"
$make_cmd olddefconfig
# verify that kernel confiration has all necessary options
while read -r opt ; do
grep "$opt" "$kconfig" &>/dev/null || skip "$opt is missing"
done < "$kho_config"
$make_cmd "$kimage"
$make_cmd headers_install INSTALL_HDR_PATH="$headers_dir"
}
function mkinitrd() {
local kernel=$1
mkdir -p "$initrd_dir"/{dev,debugfs,proc}
sudo mknod "$initrd_dir/dev/console" c 5 1
"$CROSS_COMPILE"gcc -s -static -Os -nostdinc -I"$headers_dir/include" \
-fno-asynchronous-unwind-tables -fno-ident -nostdlib \
-include "$test_dir/../../../include/nolibc/nolibc.h" \
-o "$initrd_dir/init" "$test_dir/init.c" \
cp "$kernel" "$initrd_dir/kernel"
pushd "$initrd_dir" &>/dev/null
find . | cpio -H newc --create > "$initrd" 2>/dev/null
popd &>/dev/null
}
function run_qemu() {
local qemu_cmd=$1
local cmdline=$2
local kernel=$3
local serial="$tmp_dir/qemu.serial"
cmdline="$cmdline kho=on panic=-1"
$qemu_cmd -m 1G -smp 2 -no-reboot -nographic -nodefaults \
-accel kvm -accel hvf -accel tcg \
-serial file:"$serial" \
-append "$cmdline" \
-kernel "$kernel" \
-initrd "$initrd"
grep "KHO restore succeeded" "$serial" &> /dev/null || fail "KHO failed"
}
function target_to_arch() {
local target=$1
case $target in
aarch64) echo "arm64" ;;
x86_64) echo "x86" ;;
*) skip "architecture $target is not supported"
esac
}
function main() {
local build_dir="$kernel_dir/.kho"
local jobs=$(($(nproc) * 2))
local target="$(uname -m)"
# skip the test if any of the preparation steps fails
set -o errtrace
trap skip ERR
while getopts 'hd:j:t:' opt; do
case $opt in
d)
build_dir="$OPTARG"
;;
j)
jobs="$OPTARG"
;;
t)
target="$OPTARG"
;;
h)
usage
exit 0
;;
*)
echo Unknown argument "$opt"
usage
exit 1
;;
esac
done
ktap_print_header
ktap_set_plan 1
if [[ "$target" != "$(uname -m)" ]] && [[ -z "$CROSS_COMPILE" ]]; then
skip "Cross-platform testing needs to specify CROSS_COMPILE"
fi
mkdir -p "$build_dir"
local arch=$(target_to_arch "$target")
source "$test_dir/$arch.conf"
# build the kernel and create initrd
# initrd includes the kernel image that will be kexec'ed
local make_cmd="make ARCH=$arch CROSS_COMPILE=$CROSS_COMPILE -j$jobs"
build_kernel "$build_dir" "$make_cmd" "$QEMU_KCONFIG" "$KERNEL_IMAGE"
local kernel="$build_dir/arch/$arch/boot/$KERNEL_IMAGE"
mkinitrd "$kernel"
run_qemu "$QEMU_CMD" "$KERNEL_CMDLINE" "$kernel"
ktap_test_pass "KHO succeeded"
}
main "$@"