1 #!/bin/bash 1 #!/bin/bash 2 # SPDX-License-Identifier: GPL-2.0 2 # SPDX-License-Identifier: GPL-2.0 3 3 4 set -u 4 set -u 5 set -e 5 set -e 6 6 7 # This script currently only works for x86_64 7 # This script currently only works for x86_64 8 ARCH="$(uname -m)" 8 ARCH="$(uname -m)" 9 case "${ARCH}" in 9 case "${ARCH}" in 10 x86_64) 10 x86_64) 11 QEMU_BINARY=qemu-system-x86_64 11 QEMU_BINARY=qemu-system-x86_64 12 BZIMAGE="arch/x86/boot/bzImage" 12 BZIMAGE="arch/x86/boot/bzImage" 13 ;; 13 ;; 14 *) 14 *) 15 echo "Unsupported architecture" 15 echo "Unsupported architecture" 16 exit 1 16 exit 1 17 ;; 17 ;; 18 esac 18 esac 19 SCRIPT_DIR="$(dirname $(realpath $0))" 19 SCRIPT_DIR="$(dirname $(realpath $0))" 20 OUTPUT_DIR="$SCRIPT_DIR/results" 20 OUTPUT_DIR="$SCRIPT_DIR/results" 21 KCONFIG_REL_PATHS=("${SCRIPT_DIR}/config" "${S 21 KCONFIG_REL_PATHS=("${SCRIPT_DIR}/config" "${SCRIPT_DIR}/config.common" "${SCRIPT_DIR}/config.${ARCH}") 22 B2C_URL="https://gitlab.freedesktop.org/gfx-ci 22 B2C_URL="https://gitlab.freedesktop.org/gfx-ci/boot2container/-/raw/main/vm2c.py" 23 NUM_COMPILE_JOBS="$(nproc)" 23 NUM_COMPILE_JOBS="$(nproc)" 24 LOG_FILE_BASE="$(date +"hid_selftests.%Y-%m-%d 24 LOG_FILE_BASE="$(date +"hid_selftests.%Y-%m-%d_%H-%M-%S")" 25 LOG_FILE="${LOG_FILE_BASE}.log" 25 LOG_FILE="${LOG_FILE_BASE}.log" 26 EXIT_STATUS_FILE="${LOG_FILE_BASE}.exit_status 26 EXIT_STATUS_FILE="${LOG_FILE_BASE}.exit_status" 27 CONTAINER_IMAGE="registry.freedesktop.org/bent 27 CONTAINER_IMAGE="registry.freedesktop.org/bentiss/hid/fedora/39:2023-11-22.1" 28 28 29 TARGETS="${TARGETS:=$(basename ${SCRIPT_DIR})} 29 TARGETS="${TARGETS:=$(basename ${SCRIPT_DIR})}" 30 DEFAULT_COMMAND="pip3 install hid-tools; make 30 DEFAULT_COMMAND="pip3 install hid-tools; make -C tools/testing/selftests TARGETS=${TARGETS} run_tests" 31 31 32 usage() 32 usage() 33 { 33 { 34 cat <<EOF 34 cat <<EOF 35 Usage: $0 [-j N] [-s] [-b] [-d <output_dir>] - 35 Usage: $0 [-j N] [-s] [-b] [-d <output_dir>] -- [<command>] 36 36 37 <command> is the command you would normally ru 37 <command> is the command you would normally run when you are in 38 the source kernel direcory. e.g: 38 the source kernel direcory. e.g: 39 39 40 $0 -- ./tools/testing/selftests/hid/hi 40 $0 -- ./tools/testing/selftests/hid/hid_bpf 41 41 42 If no command is specified and a debug shell ( 42 If no command is specified and a debug shell (-s) is not requested, 43 "${DEFAULT_COMMAND}" will be run by default. 43 "${DEFAULT_COMMAND}" will be run by default. 44 44 45 If you build your kernel using KBUILD_OUTPUT= 45 If you build your kernel using KBUILD_OUTPUT= or O= options, these 46 can be passed as environment variables to the 46 can be passed as environment variables to the script: 47 47 48 O=<kernel_build_path> $0 -- ./tools/testing/ 48 O=<kernel_build_path> $0 -- ./tools/testing/selftests/hid/hid_bpf 49 49 50 or 50 or 51 51 52 KBUILD_OUTPUT=<kernel_build_path> $0 -- ./to 52 KBUILD_OUTPUT=<kernel_build_path> $0 -- ./tools/testing/selftests/hid/hid_bpf 53 53 54 Options: 54 Options: 55 55 56 -u) Update the boot2contai 56 -u) Update the boot2container script to a newer version. 57 -d) Update the output dire 57 -d) Update the output directory (default: ${OUTPUT_DIR}) 58 -b) Run only the build ste 58 -b) Run only the build steps for the kernel and the selftests 59 -j) Number of jobs for com 59 -j) Number of jobs for compilation, similar to -j in make 60 (default: ${NUM_COMPIL 60 (default: ${NUM_COMPILE_JOBS}) 61 -s) Instead of powering of 61 -s) Instead of powering off the VM, start an interactive 62 shell. If <command> is 62 shell. If <command> is specified, the shell runs after 63 the command finishes e 63 the command finishes executing 64 EOF 64 EOF 65 } 65 } 66 66 67 download() 67 download() 68 { 68 { 69 local file="$1" 69 local file="$1" 70 70 71 echo "Downloading $file..." >&2 71 echo "Downloading $file..." >&2 72 curl -Lsf "$file" -o "${@:2}" 72 curl -Lsf "$file" -o "${@:2}" 73 } 73 } 74 74 75 recompile_kernel() 75 recompile_kernel() 76 { 76 { 77 local kernel_checkout="$1" 77 local kernel_checkout="$1" 78 local make_command="$2" 78 local make_command="$2" 79 79 80 cd "${kernel_checkout}" 80 cd "${kernel_checkout}" 81 81 82 ${make_command} olddefconfig 82 ${make_command} olddefconfig 83 ${make_command} headers 83 ${make_command} headers 84 ${make_command} 84 ${make_command} 85 } 85 } 86 86 87 update_selftests() 87 update_selftests() 88 { 88 { 89 local kernel_checkout="$1" 89 local kernel_checkout="$1" 90 local selftests_dir="${kernel_checkout 90 local selftests_dir="${kernel_checkout}/tools/testing/selftests/hid" 91 91 92 cd "${selftests_dir}" 92 cd "${selftests_dir}" 93 ${make_command} 93 ${make_command} 94 } 94 } 95 95 96 run_vm() 96 run_vm() 97 { 97 { 98 local run_dir="$1" 98 local run_dir="$1" 99 local b2c="$2" 99 local b2c="$2" 100 local kernel_bzimage="$3" 100 local kernel_bzimage="$3" 101 local command="$4" 101 local command="$4" 102 local post_command="" 102 local post_command="" 103 103 104 cd "${run_dir}" 104 cd "${run_dir}" 105 105 106 if ! which "${QEMU_BINARY}" &> /dev/nu 106 if ! which "${QEMU_BINARY}" &> /dev/null; then 107 cat <<EOF 107 cat <<EOF 108 Could not find ${QEMU_BINARY} 108 Could not find ${QEMU_BINARY} 109 Please install qemu or set the QEMU_BINARY env 109 Please install qemu or set the QEMU_BINARY environment variable. 110 EOF 110 EOF 111 exit 1 111 exit 1 112 fi 112 fi 113 113 114 # alpine (used in post-container requi 114 # alpine (used in post-container requires the PATH to have /bin 115 export PATH=$PATH:/bin 115 export PATH=$PATH:/bin 116 116 117 if [[ "${debug_shell}" != "yes" ]] 117 if [[ "${debug_shell}" != "yes" ]] 118 then 118 then 119 touch ${OUTPUT_DIR}/${LOG_FILE 119 touch ${OUTPUT_DIR}/${LOG_FILE} 120 command="mount bpffs -t bpf /s 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 121 post_command="cat ${OUTPUT_DIR}/${LOG_FILE}" 122 else 122 else 123 command="mount bpffs -t bpf /s 123 command="mount bpffs -t bpf /sys/fs/bpf/; ${command}" 124 fi 124 fi 125 125 126 set +e 126 set +e 127 $b2c --command "${command}" \ 127 $b2c --command "${command}" \ 128 --kernel ${kernel_bzimage} \ 128 --kernel ${kernel_bzimage} \ 129 --workdir ${OUTPUT_DIR} \ 129 --workdir ${OUTPUT_DIR} \ 130 --image ${CONTAINER_IMAGE} 130 --image ${CONTAINER_IMAGE} 131 131 132 echo $? > ${OUTPUT_DIR}/${EXIT_STATUS_ 132 echo $? > ${OUTPUT_DIR}/${EXIT_STATUS_FILE} 133 133 134 set -e 134 set -e 135 135 136 ${post_command} 136 ${post_command} 137 } 137 } 138 138 139 is_rel_path() 139 is_rel_path() 140 { 140 { 141 local path="$1" 141 local path="$1" 142 142 143 [[ ${path:0:1} != "/" ]] 143 [[ ${path:0:1} != "/" ]] 144 } 144 } 145 145 146 do_update_kconfig() 146 do_update_kconfig() 147 { 147 { 148 local kernel_checkout="$1" 148 local kernel_checkout="$1" 149 local kconfig_file="$2" 149 local kconfig_file="$2" 150 150 151 rm -f "$kconfig_file" 2> /dev/null 151 rm -f "$kconfig_file" 2> /dev/null 152 152 153 for config in "${KCONFIG_REL_PATHS[@]} 153 for config in "${KCONFIG_REL_PATHS[@]}"; do 154 local kconfig_src="${config}" 154 local kconfig_src="${config}" 155 cat "$kconfig_src" >> "$kconfi 155 cat "$kconfig_src" >> "$kconfig_file" 156 done 156 done 157 } 157 } 158 158 159 update_kconfig() 159 update_kconfig() 160 { 160 { 161 local kernel_checkout="$1" 161 local kernel_checkout="$1" 162 local kconfig_file="$2" 162 local kconfig_file="$2" 163 163 164 if [[ -f "${kconfig_file}" ]]; then 164 if [[ -f "${kconfig_file}" ]]; then 165 local local_modified="$(stat - 165 local local_modified="$(stat -c %Y "${kconfig_file}")" 166 166 167 for config in "${KCONFIG_REL_P 167 for config in "${KCONFIG_REL_PATHS[@]}"; do 168 local kconfig_src="${c 168 local kconfig_src="${config}" 169 local src_modified="$( 169 local src_modified="$(stat -c %Y "${kconfig_src}")" 170 # Only update the conf 170 # Only update the config if it has been updated after the 171 # previously cached co 171 # previously cached config was created. This avoids 172 # unnecessarily compil 172 # unnecessarily compiling the kernel and selftests. 173 if [[ "${src_modified} 173 if [[ "${src_modified}" -gt "${local_modified}" ]]; then 174 do_update_kcon 174 do_update_kconfig "$kernel_checkout" "$kconfig_file" 175 # Once we have 175 # Once we have found one outdated configuration 176 # there is no 176 # there is no need to check other ones. 177 break 177 break 178 fi 178 fi 179 done 179 done 180 else 180 else 181 do_update_kconfig "$kernel_che 181 do_update_kconfig "$kernel_checkout" "$kconfig_file" 182 fi 182 fi 183 } 183 } 184 184 185 main() 185 main() 186 { 186 { 187 local script_dir="$(cd -P -- "$(dirnam 187 local script_dir="$(cd -P -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd -P)" 188 local kernel_checkout=$(realpath "${sc 188 local kernel_checkout=$(realpath "${script_dir}"/../../../../) 189 # By default the script searches for t 189 # By default the script searches for the kernel in the checkout directory but 190 # it also obeys environment variables 190 # it also obeys environment variables O= and KBUILD_OUTPUT= 191 local kernel_bzimage="${kernel_checkou 191 local kernel_bzimage="${kernel_checkout}/${BZIMAGE}" 192 local command="${DEFAULT_COMMAND}" 192 local command="${DEFAULT_COMMAND}" 193 local update_b2c="no" 193 local update_b2c="no" 194 local debug_shell="no" 194 local debug_shell="no" 195 local build_only="no" 195 local build_only="no" 196 196 197 while getopts ':hsud:j:b' opt; do 197 while getopts ':hsud:j:b' opt; do 198 case ${opt} in 198 case ${opt} in 199 u) 199 u) 200 update_b2c="yes" 200 update_b2c="yes" 201 ;; 201 ;; 202 d) 202 d) 203 OUTPUT_DIR="$OPTARG" 203 OUTPUT_DIR="$OPTARG" 204 ;; 204 ;; 205 j) 205 j) 206 NUM_COMPILE_JOBS="$OPT 206 NUM_COMPILE_JOBS="$OPTARG" 207 ;; 207 ;; 208 s) 208 s) 209 command="/bin/sh" 209 command="/bin/sh" 210 debug_shell="yes" 210 debug_shell="yes" 211 ;; 211 ;; 212 b) 212 b) 213 build_only="yes" 213 build_only="yes" 214 ;; 214 ;; 215 h) 215 h) 216 usage 216 usage 217 exit 0 217 exit 0 218 ;; 218 ;; 219 \? ) 219 \? ) 220 echo "Invalid Option: 220 echo "Invalid Option: -$OPTARG" 221 usage 221 usage 222 exit 1 222 exit 1 223 ;; 223 ;; 224 : ) 224 : ) 225 echo "Invalid Option: 225 echo "Invalid Option: -$OPTARG requires an argument" 226 usage 226 usage 227 exit 1 227 exit 1 228 ;; 228 ;; 229 esac 229 esac 230 done 230 done 231 shift $((OPTIND -1)) 231 shift $((OPTIND -1)) 232 232 233 # trap 'catch "$?"' EXIT 233 # trap 'catch "$?"' EXIT 234 if [[ "${build_only}" == "no" && "${de 234 if [[ "${build_only}" == "no" && "${debug_shell}" == "no" ]]; then 235 if [[ $# -eq 0 ]]; then 235 if [[ $# -eq 0 ]]; then 236 echo "No command speci 236 echo "No command specified, will run ${DEFAULT_COMMAND} in the vm" 237 else 237 else 238 command="$@" 238 command="$@" 239 239 240 if [[ "${command}" == 240 if [[ "${command}" == "/bin/bash" || "${command}" == "bash" ]] 241 then 241 then 242 debug_shell="y 242 debug_shell="yes" 243 fi 243 fi 244 fi 244 fi 245 fi 245 fi 246 246 247 local kconfig_file="${OUTPUT_DIR}/late 247 local kconfig_file="${OUTPUT_DIR}/latest.config" 248 local make_command="make -j ${NUM_COMP 248 local make_command="make -j ${NUM_COMPILE_JOBS} KCONFIG_CONFIG=${kconfig_file}" 249 249 250 # Figure out where the kernel is being 250 # Figure out where the kernel is being built. 251 # O takes precedence over KBUILD_OUTPU 251 # O takes precedence over KBUILD_OUTPUT. 252 if [[ "${O:=""}" != "" ]]; then 252 if [[ "${O:=""}" != "" ]]; then 253 if is_rel_path "${O}"; then 253 if is_rel_path "${O}"; then 254 O="$(realpath "${PWD}/ 254 O="$(realpath "${PWD}/${O}")" 255 fi 255 fi 256 kernel_bzimage="${O}/${BZIMAGE 256 kernel_bzimage="${O}/${BZIMAGE}" 257 make_command="${make_command} 257 make_command="${make_command} O=${O}" 258 elif [[ "${KBUILD_OUTPUT:=""}" != "" ] 258 elif [[ "${KBUILD_OUTPUT:=""}" != "" ]]; then 259 if is_rel_path "${KBUILD_OUTPU 259 if is_rel_path "${KBUILD_OUTPUT}"; then 260 KBUILD_OUTPUT="$(realp 260 KBUILD_OUTPUT="$(realpath "${PWD}/${KBUILD_OUTPUT}")" 261 fi 261 fi 262 kernel_bzimage="${KBUILD_OUTPU 262 kernel_bzimage="${KBUILD_OUTPUT}/${BZIMAGE}" 263 make_command="${make_command} 263 make_command="${make_command} KBUILD_OUTPUT=${KBUILD_OUTPUT}" 264 fi 264 fi 265 265 266 local b2c="${OUTPUT_DIR}/vm2c.py" 266 local b2c="${OUTPUT_DIR}/vm2c.py" 267 267 268 echo "Output directory: ${OUTPUT_DIR}" 268 echo "Output directory: ${OUTPUT_DIR}" 269 269 270 mkdir -p "${OUTPUT_DIR}" 270 mkdir -p "${OUTPUT_DIR}" 271 update_kconfig "${kernel_checkout}" "$ 271 update_kconfig "${kernel_checkout}" "${kconfig_file}" 272 272 273 recompile_kernel "${kernel_checkout}" 273 recompile_kernel "${kernel_checkout}" "${make_command}" 274 update_selftests "${kernel_checkout}" 274 update_selftests "${kernel_checkout}" "${make_command}" 275 275 276 if [[ "${build_only}" == "no" ]]; then 276 if [[ "${build_only}" == "no" ]]; then 277 if [[ "${update_b2c}" == "no" 277 if [[ "${update_b2c}" == "no" && ! -f "${b2c}" ]]; then 278 echo "vm2c script not 278 echo "vm2c script not found in ${b2c}" 279 update_b2c="yes" 279 update_b2c="yes" 280 fi 280 fi 281 281 282 if [[ "${update_b2c}" == "yes" 282 if [[ "${update_b2c}" == "yes" ]]; then 283 download $B2C_URL $b2c 283 download $B2C_URL $b2c 284 chmod +x $b2c 284 chmod +x $b2c 285 fi 285 fi 286 286 287 run_vm "${kernel_checkout}" $b 287 run_vm "${kernel_checkout}" $b2c "${kernel_bzimage}" "${command}" 288 if [[ "${debug_shell}" != "yes 288 if [[ "${debug_shell}" != "yes" ]]; then 289 echo "Logs saved in ${ 289 echo "Logs saved in ${OUTPUT_DIR}/${LOG_FILE}" 290 fi 290 fi 291 291 292 exit $(cat ${OUTPUT_DIR}/${EXI 292 exit $(cat ${OUTPUT_DIR}/${EXIT_STATUS_FILE}) 293 fi 293 fi 294 } 294 } 295 295 296 main "$@" 296 main "$@"
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.