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