Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
1#!/bin/bash
2# SPDX-License-Identifier: GPL-2.0
3
4set -u
5set -e
6
7# This script currently only works for x86_64
8ARCH="$(uname -m)"
9case "${ARCH}" in
10x86_64)
11 QEMU_BINARY=qemu-system-x86_64
12 BZIMAGE="arch/x86/boot/bzImage"
13 ;;
14*)
15 echo "Unsupported architecture"
16 exit 1
17 ;;
18esac
19SCRIPT_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 <<EOF
35Usage: $0 [-j N] [-s] [-b] [-d <output_dir>] -- [<command>]
36
37<command> is the command you would normally run when you are in
38the source kernel direcory. e.g:
39
40 $0 -- ./tools/testing/selftests/hid/hid_bpf
41
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, these
46can be passed as environment variables to the script:
47
48 O=<kernel_build_path> $0 -- ./tools/testing/selftests/hid/hid_bpf
49
50or
51
52 KBUILD_OUTPUT=<kernel_build_path> $0 -- ./tools/testing/selftests/hid/hid_bpf
53
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 selftests
59 -j) Number of jobs for compilation, similar to -j in make
60 (default: ${NUM_COMPILE_JOBS})
61 -s) Instead of powering off the VM, start an interactive
62 shell. If <command> is specified, the shell runs after
63 the command finishes executing
64EOF
65}
66
67download()
68{
69 local file="$1"
70
71 echo "Downloading $file..." >&2
72 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} olddefconfig
83 ${make_command} headers
84 ${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; then
107 cat <<EOF
108Could not find ${QEMU_BINARY}
109Please install qemu or set the QEMU_BINARY environment variable.
110EOF
111 exit 1
112 fi
113
114 # alpine (used in post-container requires the PATH to have /bin
115 export PATH=$PATH:/bin
116
117 if [[ "${debug_shell}" != "yes" ]]
118 then
119 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 else
123 command="mount bpffs -t bpf /sys/fs/bpf/; ${command}"
124 fi
125
126 set +e
127 $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 -e
135
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/null
152
153 for config in "${KCONFIG_REL_PATHS[@]}"; do
154 local kconfig_src="${config}"
155 cat "$kconfig_src" >> "$kconfig_file"
156 done
157}
158
159update_kconfig()
160{
161 local kernel_checkout="$1"
162 local kconfig_file="$2"
163
164 if [[ -f "${kconfig_file}" ]]; then
165 local local_modified="$(stat -c %Y "${kconfig_file}")"
166
167 for config in "${KCONFIG_REL_PATHS[@]}"; do
168 local kconfig_src="${config}"
169 local src_modified="$(stat -c %Y "${kconfig_src}")"
170 # Only update the config if it has been updated after the
171 # previously cached config was created. This avoids
172 # unnecessarily compiling the kernel and selftests.
173 if [[ "${src_modified}" -gt "${local_modified}" ]]; then
174 do_update_kconfig "$kernel_checkout" "$kconfig_file"
175 # Once we have found one outdated configuration
176 # there is no need to check other ones.
177 break
178 fi
179 done
180 else
181 do_update_kconfig "$kernel_checkout" "$kconfig_file"
182 fi
183}
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 but
190 # 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; do
198 case ${opt} in
199 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 usage
217 exit 0
218 ;;
219 \? )
220 echo "Invalid Option: -$OPTARG"
221 usage
222 exit 1
223 ;;
224 : )
225 echo "Invalid Option: -$OPTARG requires an argument"
226 usage
227 exit 1
228 ;;
229 esac
230 done
231 shift $((OPTIND -1))
232
233 # trap 'catch "$?"' EXIT
234 if [[ "${build_only}" == "no" && "${debug_shell}" == "no" ]]; then
235 if [[ $# -eq 0 ]]; then
236 echo "No command specified, will run ${DEFAULT_COMMAND} in the vm"
237 else
238 command="$@"
239
240 if [[ "${command}" == "/bin/bash" || "${command}" == "bash" ]]
241 then
242 debug_shell="yes"
243 fi
244 fi
245 fi
246
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:=""}" != "" ]]; then
253 if is_rel_path "${O}"; then
254 O="$(realpath "${PWD}/${O}")"
255 fi
256 kernel_bzimage="${O}/${BZIMAGE}"
257 make_command="${make_command} O=${O}"
258 elif [[ "${KBUILD_OUTPUT:=""}" != "" ]]; then
259 if is_rel_path "${KBUILD_OUTPUT}"; then
260 KBUILD_OUTPUT="$(realpath "${PWD}/${KBUILD_OUTPUT}")"
261 fi
262 kernel_bzimage="${KBUILD_OUTPUT}/${BZIMAGE}"
263 make_command="${make_command} KBUILD_OUTPUT=${KBUILD_OUTPUT}"
264 fi
265
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" ]]; then
277 if [[ "${update_b2c}" == "no" && ! -f "${b2c}" ]]; then
278 echo "vm2c script not found in ${b2c}"
279 update_b2c="yes"
280 fi
281
282 if [[ "${update_b2c}" == "yes" ]]; then
283 download $B2C_URL $b2c
284 chmod +x $b2c
285 fi
286
287 run_vm "${kernel_checkout}" $b2c "${kernel_bzimage}" "${command}"
288 if [[ "${debug_shell}" != "yes" ]]; then
289 echo "Logs saved in ${OUTPUT_DIR}/${LOG_FILE}"
290 fi
291
292 exit $(cat ${OUTPUT_DIR}/${EXIT_STATUS_FILE})
293 fi
294}
295
296main "$@"