297 lines · bash
1#!/bin/bash2# SPDX-License-Identifier: GPL-2.03 4set -u5set -e6 7# This script currently only works for x86_648ARCH="$(uname -m)"9case "${ARCH}" in10x86_64)11 QEMU_BINARY=qemu-system-x86_6412 BZIMAGE="arch/x86/boot/bzImage"13 ;;14*)15 echo "Unsupported architecture"16 exit 117 ;;18esac19SCRIPT_DIR="$(dirname $(realpath $0))"20OUTPUT_DIR="$SCRIPT_DIR/results"21KCONFIG_REL_PATHS=("${SCRIPT_DIR}/config" "${SCRIPT_DIR}/config.common" "${SCRIPT_DIR}/config.${ARCH}")22B2C_URL="https://gitlab.freedesktop.org/gfx-ci/boot2container/-/raw/main/vm2c.py"23NUM_COMPILE_JOBS="$(nproc)"24LOG_FILE_BASE="$(date +"hid_selftests.%Y-%m-%d_%H-%M-%S")"25LOG_FILE="${LOG_FILE_BASE}.log"26EXIT_STATUS_FILE="${LOG_FILE_BASE}.exit_status"27CONTAINER_IMAGE="registry.freedesktop.org/bentiss/hid/fedora/39:2023-11-22.1"28 29TARGETS="${TARGETS:=$(basename ${SCRIPT_DIR})}"30DEFAULT_COMMAND="pip3 install hid-tools; make -C tools/testing/selftests TARGETS=${TARGETS} run_tests"31 32usage()33{34 cat <<EOF35Usage: $0 [-j N] [-s] [-b] [-d <output_dir>] -- [<command>]36 37<command> is the command you would normally run when you are in38the source kernel direcory. e.g:39 40 $0 -- ./tools/testing/selftests/hid/hid_bpf41 42If no command is specified and a debug shell (-s) is not requested,43"${DEFAULT_COMMAND}" will be run by default.44 45If you build your kernel using KBUILD_OUTPUT= or O= options, these46can be passed as environment variables to the script:47 48 O=<kernel_build_path> $0 -- ./tools/testing/selftests/hid/hid_bpf49 50or51 52 KBUILD_OUTPUT=<kernel_build_path> $0 -- ./tools/testing/selftests/hid/hid_bpf53 54Options:55 56 -u) Update the boot2container script to a newer version.57 -d) Update the output directory (default: ${OUTPUT_DIR})58 -b) Run only the build steps for the kernel and the selftests59 -j) Number of jobs for compilation, similar to -j in make60 (default: ${NUM_COMPILE_JOBS})61 -s) Instead of powering off the VM, start an interactive62 shell. If <command> is specified, the shell runs after63 the command finishes executing64EOF65}66 67download()68{69 local file="$1"70 71 echo "Downloading $file..." >&272 curl -Lsf "$file" -o "${@:2}"73}74 75recompile_kernel()76{77 local kernel_checkout="$1"78 local make_command="$2"79 80 cd "${kernel_checkout}"81 82 ${make_command} olddefconfig83 ${make_command} headers84 ${make_command}85}86 87update_selftests()88{89 local kernel_checkout="$1"90 local selftests_dir="${kernel_checkout}/tools/testing/selftests/hid"91 92 cd "${selftests_dir}"93 ${make_command}94}95 96run_vm()97{98 local run_dir="$1"99 local b2c="$2"100 local kernel_bzimage="$3"101 local command="$4"102 local post_command=""103 104 cd "${run_dir}"105 106 if ! which "${QEMU_BINARY}" &> /dev/null; then107 cat <<EOF108Could not find ${QEMU_BINARY}109Please install qemu or set the QEMU_BINARY environment variable.110EOF111 exit 1112 fi113 114 # alpine (used in post-container requires the PATH to have /bin115 export PATH=$PATH:/bin116 117 if [[ "${debug_shell}" != "yes" ]]118 then119 touch ${OUTPUT_DIR}/${LOG_FILE}120 command="mount bpffs -t bpf /sys/fs/bpf/; set -o pipefail ; ${command} 2>&1 | tee ${OUTPUT_DIR}/${LOG_FILE}"121 post_command="cat ${OUTPUT_DIR}/${LOG_FILE}"122 else123 command="mount bpffs -t bpf /sys/fs/bpf/; ${command}"124 fi125 126 set +e127 $b2c --command "${command}" \128 --kernel ${kernel_bzimage} \129 --workdir ${OUTPUT_DIR} \130 --image ${CONTAINER_IMAGE}131 132 echo $? > ${OUTPUT_DIR}/${EXIT_STATUS_FILE}133 134 set -e135 136 ${post_command}137}138 139is_rel_path()140{141 local path="$1"142 143 [[ ${path:0:1} != "/" ]]144}145 146do_update_kconfig()147{148 local kernel_checkout="$1"149 local kconfig_file="$2"150 151 rm -f "$kconfig_file" 2> /dev/null152 153 for config in "${KCONFIG_REL_PATHS[@]}"; do154 local kconfig_src="${config}"155 cat "$kconfig_src" >> "$kconfig_file"156 done157}158 159update_kconfig()160{161 local kernel_checkout="$1"162 local kconfig_file="$2"163 164 if [[ -f "${kconfig_file}" ]]; then165 local local_modified="$(stat -c %Y "${kconfig_file}")"166 167 for config in "${KCONFIG_REL_PATHS[@]}"; do168 local kconfig_src="${config}"169 local src_modified="$(stat -c %Y "${kconfig_src}")"170 # Only update the config if it has been updated after the171 # previously cached config was created. This avoids172 # unnecessarily compiling the kernel and selftests.173 if [[ "${src_modified}" -gt "${local_modified}" ]]; then174 do_update_kconfig "$kernel_checkout" "$kconfig_file"175 # Once we have found one outdated configuration176 # there is no need to check other ones.177 break178 fi179 done180 else181 do_update_kconfig "$kernel_checkout" "$kconfig_file"182 fi183}184 185main()186{187 local script_dir="$(cd -P -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd -P)"188 local kernel_checkout=$(realpath "${script_dir}"/../../../../)189 # By default the script searches for the kernel in the checkout directory but190 # it also obeys environment variables O= and KBUILD_OUTPUT=191 local kernel_bzimage="${kernel_checkout}/${BZIMAGE}"192 local command="${DEFAULT_COMMAND}"193 local update_b2c="no"194 local debug_shell="no"195 local build_only="no"196 197 while getopts ':hsud:j:b' opt; do198 case ${opt} in199 u)200 update_b2c="yes"201 ;;202 d)203 OUTPUT_DIR="$OPTARG"204 ;;205 j)206 NUM_COMPILE_JOBS="$OPTARG"207 ;;208 s)209 command="/bin/sh"210 debug_shell="yes"211 ;;212 b)213 build_only="yes"214 ;;215 h)216 usage217 exit 0218 ;;219 \? )220 echo "Invalid Option: -$OPTARG"221 usage222 exit 1223 ;;224 : )225 echo "Invalid Option: -$OPTARG requires an argument"226 usage227 exit 1228 ;;229 esac230 done231 shift $((OPTIND -1))232 233 # trap 'catch "$?"' EXIT234 if [[ "${build_only}" == "no" && "${debug_shell}" == "no" ]]; then235 if [[ $# -eq 0 ]]; then236 echo "No command specified, will run ${DEFAULT_COMMAND} in the vm"237 else238 command="$@"239 240 if [[ "${command}" == "/bin/bash" || "${command}" == "bash" ]]241 then242 debug_shell="yes"243 fi244 fi245 fi246 247 local kconfig_file="${OUTPUT_DIR}/latest.config"248 local make_command="make -j ${NUM_COMPILE_JOBS} KCONFIG_CONFIG=${kconfig_file}"249 250 # Figure out where the kernel is being built.251 # O takes precedence over KBUILD_OUTPUT.252 if [[ "${O:=""}" != "" ]]; then253 if is_rel_path "${O}"; then254 O="$(realpath "${PWD}/${O}")"255 fi256 kernel_bzimage="${O}/${BZIMAGE}"257 make_command="${make_command} O=${O}"258 elif [[ "${KBUILD_OUTPUT:=""}" != "" ]]; then259 if is_rel_path "${KBUILD_OUTPUT}"; then260 KBUILD_OUTPUT="$(realpath "${PWD}/${KBUILD_OUTPUT}")"261 fi262 kernel_bzimage="${KBUILD_OUTPUT}/${BZIMAGE}"263 make_command="${make_command} KBUILD_OUTPUT=${KBUILD_OUTPUT}"264 fi265 266 local b2c="${OUTPUT_DIR}/vm2c.py"267 268 echo "Output directory: ${OUTPUT_DIR}"269 270 mkdir -p "${OUTPUT_DIR}"271 update_kconfig "${kernel_checkout}" "${kconfig_file}"272 273 recompile_kernel "${kernel_checkout}" "${make_command}"274 update_selftests "${kernel_checkout}" "${make_command}"275 276 if [[ "${build_only}" == "no" ]]; then277 if [[ "${update_b2c}" == "no" && ! -f "${b2c}" ]]; then278 echo "vm2c script not found in ${b2c}"279 update_b2c="yes"280 fi281 282 if [[ "${update_b2c}" == "yes" ]]; then283 download $B2C_URL $b2c284 chmod +x $b2c285 fi286 287 run_vm "${kernel_checkout}" $b2c "${kernel_bzimage}" "${command}"288 if [[ "${debug_shell}" != "yes" ]]; then289 echo "Logs saved in ${OUTPUT_DIR}/${LOG_FILE}"290 fi291 292 exit $(cat ${OUTPUT_DIR}/${EXIT_STATUS_FILE})293 fi294}295 296main "$@"297