vmtest.sh 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. #!/bin/bash
  2. # SPDX-License-Identifier: GPL-2.0
  3. set -ue
  4. CROSS_COMPILE="${CROSS_COMPILE:-""}"
  5. test_dir=$(realpath "$(dirname "$0")")
  6. kernel_dir=$(realpath "$test_dir/../../../..")
  7. tmp_dir=$(mktemp -d /tmp/kho-test.XXXXXXXX)
  8. headers_dir="$tmp_dir/usr"
  9. initrd="$tmp_dir/initrd.cpio"
  10. source "$test_dir/../kselftest/ktap_helpers.sh"
  11. function usage() {
  12. cat <<EOF
  13. $0 [-d build_dir] [-j jobs] [-t target_arch] [-h]
  14. Options:
  15. -d) path to the kernel build directory
  16. -j) number of jobs for compilation, similar to -j in make
  17. -t) run test for target_arch, requires CROSS_COMPILE set
  18. supported targets: aarch64, x86_64
  19. -h) display this help
  20. EOF
  21. }
  22. function cleanup() {
  23. rm -fr "$tmp_dir"
  24. ktap_finished
  25. }
  26. trap cleanup EXIT
  27. function skip() {
  28. local msg=${1:-""}
  29. ktap_test_skip "$msg"
  30. exit "$KSFT_SKIP"
  31. }
  32. function fail() {
  33. local msg=${1:-""}
  34. ktap_test_fail "$msg"
  35. exit "$KSFT_FAIL"
  36. }
  37. function build_kernel() {
  38. local build_dir=$1
  39. local make_cmd=$2
  40. local arch_kconfig=$3
  41. local kimage=$4
  42. local kho_config="$tmp_dir/kho.config"
  43. local kconfig="$build_dir/.config"
  44. # enable initrd, KHO and KHO test in kernel configuration
  45. tee "$kconfig" > "$kho_config" <<EOF
  46. CONFIG_BLK_DEV_INITRD=y
  47. CONFIG_KEXEC_HANDOVER=y
  48. CONFIG_KEXEC_HANDOVER_DEBUGFS=y
  49. CONFIG_TEST_KEXEC_HANDOVER=y
  50. CONFIG_DEBUG_KERNEL=y
  51. CONFIG_DEBUG_VM=y
  52. $arch_kconfig
  53. EOF
  54. make_cmd="$make_cmd -C $kernel_dir O=$build_dir"
  55. $make_cmd olddefconfig
  56. # verify that kernel confiration has all necessary options
  57. while read -r opt ; do
  58. grep "$opt" "$kconfig" &>/dev/null || skip "$opt is missing"
  59. done < "$kho_config"
  60. $make_cmd "$kimage"
  61. $make_cmd headers_install INSTALL_HDR_PATH="$headers_dir"
  62. }
  63. function mkinitrd() {
  64. local kernel=$1
  65. "$CROSS_COMPILE"gcc -s -static -Os -nostdinc -nostdlib \
  66. -fno-asynchronous-unwind-tables -fno-ident \
  67. -I "$headers_dir/include" \
  68. -I "$kernel_dir/tools/include/nolibc" \
  69. -o "$tmp_dir/init" "$test_dir/init.c"
  70. cat > "$tmp_dir/cpio_list" <<EOF
  71. dir /dev 0755 0 0
  72. dir /proc 0755 0 0
  73. dir /debugfs 0755 0 0
  74. nod /dev/console 0600 0 0 c 5 1
  75. file /init $tmp_dir/init 0755 0 0
  76. file /kernel $kernel 0644 0 0
  77. EOF
  78. "$build_dir/usr/gen_init_cpio" "$tmp_dir/cpio_list" > "$initrd"
  79. }
  80. function run_qemu() {
  81. local qemu_cmd=$1
  82. local cmdline=$2
  83. local kernel=$3
  84. local serial="$tmp_dir/qemu.serial"
  85. cmdline="$cmdline kho=on panic=-1"
  86. $qemu_cmd -m 1G -smp 2 -no-reboot -nographic -nodefaults \
  87. -accel kvm -accel hvf -accel tcg \
  88. -serial file:"$serial" \
  89. -append "$cmdline" \
  90. -kernel "$kernel" \
  91. -initrd "$initrd"
  92. grep "KHO restore succeeded" "$serial" &> /dev/null || fail "KHO failed"
  93. }
  94. function target_to_arch() {
  95. local target=$1
  96. case $target in
  97. aarch64) echo "arm64" ;;
  98. x86_64) echo "x86" ;;
  99. *) skip "architecture $target is not supported"
  100. esac
  101. }
  102. function main() {
  103. local build_dir="$kernel_dir/.kho"
  104. local jobs=$(($(nproc) * 2))
  105. local target="$(uname -m)"
  106. # skip the test if any of the preparation steps fails
  107. set -o errtrace
  108. trap skip ERR
  109. while getopts 'hd:j:t:' opt; do
  110. case $opt in
  111. d)
  112. build_dir="$OPTARG"
  113. ;;
  114. j)
  115. jobs="$OPTARG"
  116. ;;
  117. t)
  118. target="$OPTARG"
  119. ;;
  120. h)
  121. usage
  122. exit 0
  123. ;;
  124. *)
  125. echo Unknown argument "$opt"
  126. usage
  127. exit 1
  128. ;;
  129. esac
  130. done
  131. ktap_print_header
  132. ktap_set_plan 1
  133. if [[ "$target" != "$(uname -m)" ]] && [[ -z "$CROSS_COMPILE" ]]; then
  134. skip "Cross-platform testing needs to specify CROSS_COMPILE"
  135. fi
  136. mkdir -p "$build_dir"
  137. local arch=$(target_to_arch "$target")
  138. source "$test_dir/$arch.conf"
  139. # build the kernel and create initrd
  140. # initrd includes the kernel image that will be kexec'ed
  141. local make_cmd="make ARCH=$arch CROSS_COMPILE=$CROSS_COMPILE -j$jobs"
  142. build_kernel "$build_dir" "$make_cmd" "$QEMU_KCONFIG" "$KERNEL_IMAGE"
  143. local kernel="$build_dir/arch/$arch/boot/$KERNEL_IMAGE"
  144. mkinitrd "$kernel"
  145. run_qemu "$QEMU_CMD" "$KERNEL_CMDLINE" "$kernel"
  146. ktap_test_pass "KHO succeeded"
  147. }
  148. main "$@"