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