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