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