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