| .. | .. |
|---|
| 1 | 1 | #!/bin/bash |
|---|
| 2 | +# SPDX-License-Identifier: GPL-2.0+ |
|---|
| 2 | 3 | # |
|---|
| 3 | 4 | # Run a kvm-based test of the specified tree on the specified configs. |
|---|
| 4 | 5 | # Fully automated run and error checking, no graphics console. |
|---|
| .. | .. |
|---|
| 20 | 21 | # |
|---|
| 21 | 22 | # More sophisticated argument parsing is clearly needed. |
|---|
| 22 | 23 | # |
|---|
| 23 | | -# This program is free software; you can redistribute it and/or modify |
|---|
| 24 | | -# it under the terms of the GNU General Public License as published by |
|---|
| 25 | | -# the Free Software Foundation; either version 2 of the License, or |
|---|
| 26 | | -# (at your option) any later version. |
|---|
| 27 | | -# |
|---|
| 28 | | -# This program is distributed in the hope that it will be useful, |
|---|
| 29 | | -# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|---|
| 30 | | -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|---|
| 31 | | -# GNU General Public License for more details. |
|---|
| 32 | | -# |
|---|
| 33 | | -# You should have received a copy of the GNU General Public License |
|---|
| 34 | | -# along with this program; if not, you can access it online at |
|---|
| 35 | | -# http://www.gnu.org/licenses/gpl-2.0.html. |
|---|
| 36 | | -# |
|---|
| 37 | 24 | # Copyright (C) IBM Corporation, 2011 |
|---|
| 38 | 25 | # |
|---|
| 39 | | -# Authors: Paul E. McKenney <paulmck@linux.vnet.ibm.com> |
|---|
| 26 | +# Authors: Paul E. McKenney <paulmck@linux.ibm.com> |
|---|
| 40 | 27 | |
|---|
| 41 | 28 | T=${TMPDIR-/tmp}/kvm-test-1-run.sh.$$ |
|---|
| 42 | 29 | trap 'rm -rf $T' 0 |
|---|
| .. | .. |
|---|
| 49 | 36 | config_dir=`echo $config_template | sed -e 's,/[^/]*$,,'` |
|---|
| 50 | 37 | title=`echo $config_template | sed -e 's/^.*\///'` |
|---|
| 51 | 38 | builddir=${2} |
|---|
| 52 | | -if test -z "$builddir" -o ! -d "$builddir" -o ! -w "$builddir" |
|---|
| 53 | | -then |
|---|
| 54 | | - echo "kvm-test-1-run.sh :$builddir: Not a writable directory, cannot build into it" |
|---|
| 55 | | - exit 1 |
|---|
| 56 | | -fi |
|---|
| 57 | 39 | resdir=${3} |
|---|
| 58 | 40 | if test -z "$resdir" -o ! -d "$resdir" -o ! -w "$resdir" |
|---|
| 59 | 41 | then |
|---|
| .. | .. |
|---|
| 62 | 44 | fi |
|---|
| 63 | 45 | echo ' ---' `date`: Starting build |
|---|
| 64 | 46 | echo ' ---' Kconfig fragment at: $config_template >> $resdir/log |
|---|
| 65 | | -touch $resdir/ConfigFragment.input $resdir/ConfigFragment |
|---|
| 66 | | -if test -r "$config_dir/CFcommon" |
|---|
| 67 | | -then |
|---|
| 68 | | - echo " --- $config_dir/CFcommon" >> $resdir/ConfigFragment.input |
|---|
| 69 | | - cat < $config_dir/CFcommon >> $resdir/ConfigFragment.input |
|---|
| 70 | | - config_override.sh $config_dir/CFcommon $config_template > $T/Kc1 |
|---|
| 71 | | - grep '#CHECK#' $config_dir/CFcommon >> $resdir/ConfigFragment |
|---|
| 72 | | -else |
|---|
| 73 | | - cp $config_template $T/Kc1 |
|---|
| 74 | | -fi |
|---|
| 75 | | -echo " --- $config_template" >> $resdir/ConfigFragment.input |
|---|
| 76 | | -cat $config_template >> $resdir/ConfigFragment.input |
|---|
| 77 | | -grep '#CHECK#' $config_template >> $resdir/ConfigFragment |
|---|
| 78 | | -if test -n "$TORTURE_KCONFIG_ARG" |
|---|
| 79 | | -then |
|---|
| 80 | | - echo $TORTURE_KCONFIG_ARG | tr -s " " "\012" > $T/cmdline |
|---|
| 81 | | - echo " --- --kconfig argument" >> $resdir/ConfigFragment.input |
|---|
| 82 | | - cat $T/cmdline >> $resdir/ConfigFragment.input |
|---|
| 83 | | - config_override.sh $T/Kc1 $T/cmdline > $T/Kc2 |
|---|
| 84 | | - # Note that "#CHECK#" is not permitted on commandline. |
|---|
| 85 | | -else |
|---|
| 86 | | - cp $T/Kc1 $T/Kc2 |
|---|
| 87 | | -fi |
|---|
| 88 | | -cat $T/Kc2 >> $resdir/ConfigFragment |
|---|
| 47 | +touch $resdir/ConfigFragment.input |
|---|
| 48 | + |
|---|
| 49 | +# Combine additional Kconfig options into an existing set such that |
|---|
| 50 | +# newer options win. The first argument is the Kconfig source ID, the |
|---|
| 51 | +# second the to-be-updated file within $T, and the third and final the |
|---|
| 52 | +# list of additional Kconfig options. Note that a $2.tmp file is |
|---|
| 53 | +# created when doing the update. |
|---|
| 54 | +config_override_param () { |
|---|
| 55 | + if test -n "$3" |
|---|
| 56 | + then |
|---|
| 57 | + echo $3 | sed -e 's/^ *//' -e 's/ *$//' | tr -s " " "\012" > $T/Kconfig_args |
|---|
| 58 | + echo " --- $1" >> $resdir/ConfigFragment.input |
|---|
| 59 | + cat $T/Kconfig_args >> $resdir/ConfigFragment.input |
|---|
| 60 | + config_override.sh $T/$2 $T/Kconfig_args > $T/$2.tmp |
|---|
| 61 | + mv $T/$2.tmp $T/$2 |
|---|
| 62 | + # Note that "#CHECK#" is not permitted on commandline. |
|---|
| 63 | + fi |
|---|
| 64 | +} |
|---|
| 65 | + |
|---|
| 66 | +echo > $T/KcList |
|---|
| 67 | +config_override_param "$config_dir/CFcommon" KcList "`cat $config_dir/CFcommon 2> /dev/null`" |
|---|
| 68 | +config_override_param "$config_template" KcList "`cat $config_template 2> /dev/null`" |
|---|
| 69 | +config_override_param "--gdb options" KcList "$TORTURE_KCONFIG_GDB_ARG" |
|---|
| 70 | +config_override_param "--kasan options" KcList "$TORTURE_KCONFIG_KASAN_ARG" |
|---|
| 71 | +config_override_param "--kcsan options" KcList "$TORTURE_KCONFIG_KCSAN_ARG" |
|---|
| 72 | +config_override_param "--kconfig argument" KcList "$TORTURE_KCONFIG_ARG" |
|---|
| 73 | +cp $T/KcList $resdir/ConfigFragment |
|---|
| 89 | 74 | |
|---|
| 90 | 75 | base_resdir=`echo $resdir | sed -e 's/\.[0-9]\+$//'` |
|---|
| 91 | 76 | if test "$base_resdir" != "$resdir" -a -f $base_resdir/bzImage -a -f $base_resdir/vmlinux |
|---|
| .. | .. |
|---|
| 98 | 83 | ln -s $base_resdir/.config $resdir # for kvm-recheck.sh |
|---|
| 99 | 84 | # Arch-independent indicator |
|---|
| 100 | 85 | touch $resdir/builtkernel |
|---|
| 101 | | -elif kvm-build.sh $T/Kc2 $builddir $resdir |
|---|
| 86 | +elif kvm-build.sh $T/KcList $resdir |
|---|
| 102 | 87 | then |
|---|
| 103 | 88 | # Had to build a kernel for this test. |
|---|
| 104 | | - QEMU="`identify_qemu $builddir/vmlinux`" |
|---|
| 89 | + QEMU="`identify_qemu vmlinux`" |
|---|
| 105 | 90 | BOOT_IMAGE="`identify_boot_image $QEMU`" |
|---|
| 106 | | - cp $builddir/vmlinux $resdir |
|---|
| 107 | | - cp $builddir/.config $resdir |
|---|
| 108 | | - cp $builddir/Module.symvers $resdir > /dev/null || : |
|---|
| 109 | | - cp $builddir/System.map $resdir > /dev/null || : |
|---|
| 91 | + cp vmlinux $resdir |
|---|
| 92 | + cp .config $resdir |
|---|
| 93 | + cp Module.symvers $resdir > /dev/null || : |
|---|
| 94 | + cp System.map $resdir > /dev/null || : |
|---|
| 110 | 95 | if test -n "$BOOT_IMAGE" |
|---|
| 111 | 96 | then |
|---|
| 112 | | - cp $builddir/$BOOT_IMAGE $resdir |
|---|
| 97 | + cp $BOOT_IMAGE $resdir |
|---|
| 113 | 98 | KERNEL=$resdir/${BOOT_IMAGE##*/} |
|---|
| 114 | 99 | # Arch-independent indicator |
|---|
| 115 | 100 | touch $resdir/builtkernel |
|---|
| .. | .. |
|---|
| 120 | 105 | parse-build.sh $resdir/Make.out $title |
|---|
| 121 | 106 | else |
|---|
| 122 | 107 | # Build failed. |
|---|
| 123 | | - cp $builddir/Make*.out $resdir |
|---|
| 124 | | - cp $builddir/.config $resdir || : |
|---|
| 108 | + cp .config $resdir || : |
|---|
| 125 | 109 | echo Build failed, not running KVM, see $resdir. |
|---|
| 126 | 110 | if test -f $builddir.wait |
|---|
| 127 | 111 | then |
|---|
| .. | .. |
|---|
| 141 | 125 | qemu_args=$5 |
|---|
| 142 | 126 | boot_args=$6 |
|---|
| 143 | 127 | |
|---|
| 144 | | -cd $KVM |
|---|
| 145 | | -kstarttime=`awk 'BEGIN { print systime() }' < /dev/null` |
|---|
| 128 | +kstarttime=`gawk 'BEGIN { print systime() }' < /dev/null` |
|---|
| 146 | 129 | if test -z "$TORTURE_BUILDONLY" |
|---|
| 147 | 130 | then |
|---|
| 148 | 131 | echo ' ---' `date`: Starting kernel |
|---|
| .. | .. |
|---|
| 152 | 135 | qemu_args="-enable-kvm -nographic $qemu_args" |
|---|
| 153 | 136 | cpu_count=`configNR_CPUS.sh $resdir/ConfigFragment` |
|---|
| 154 | 137 | cpu_count=`configfrag_boot_cpus "$boot_args" "$config_template" "$cpu_count"` |
|---|
| 155 | | -vcpus=`identify_qemu_vcpus` |
|---|
| 156 | | -if test $cpu_count -gt $vcpus |
|---|
| 138 | +if test "$cpu_count" -gt "$TORTURE_ALLOTED_CPUS" |
|---|
| 157 | 139 | then |
|---|
| 158 | | - echo CPU count limited from $cpu_count to $vcpus | tee -a $resdir/Warnings |
|---|
| 159 | | - cpu_count=$vcpus |
|---|
| 140 | + echo CPU count limited from $cpu_count to $TORTURE_ALLOTED_CPUS | tee -a $resdir/Warnings |
|---|
| 141 | + cpu_count=$TORTURE_ALLOTED_CPUS |
|---|
| 160 | 142 | fi |
|---|
| 161 | 143 | qemu_args="`specify_qemu_cpus "$QEMU" "$qemu_args" "$cpu_count"`" |
|---|
| 144 | +qemu_args="`specify_qemu_net "$qemu_args"`" |
|---|
| 162 | 145 | |
|---|
| 163 | 146 | # Generate architecture-specific and interaction-specific qemu arguments |
|---|
| 164 | 147 | qemu_args="$qemu_args `identify_qemu_args "$QEMU" "$resdir/console.log"`" |
|---|
| .. | .. |
|---|
| 170 | 153 | boot_args="`configfrag_boot_params "$boot_args" "$config_template"`" |
|---|
| 171 | 154 | # Generate kernel-version-specific boot parameters |
|---|
| 172 | 155 | boot_args="`per_version_boot_params "$boot_args" $resdir/.config $seconds`" |
|---|
| 156 | +if test -n "$TORTURE_BOOT_GDB_ARG" |
|---|
| 157 | +then |
|---|
| 158 | + boot_args="$boot_args $TORTURE_BOOT_GDB_ARG" |
|---|
| 159 | +fi |
|---|
| 160 | +echo $QEMU $qemu_args -m $TORTURE_QEMU_MEM -kernel $KERNEL -append \"$qemu_append $boot_args\" $TORTURE_QEMU_GDB_ARG > $resdir/qemu-cmd |
|---|
| 173 | 161 | |
|---|
| 174 | 162 | if test -n "$TORTURE_BUILDONLY" |
|---|
| 175 | 163 | then |
|---|
| .. | .. |
|---|
| 177 | 165 | touch $resdir/buildonly |
|---|
| 178 | 166 | exit 0 |
|---|
| 179 | 167 | fi |
|---|
| 168 | + |
|---|
| 169 | +# Decorate qemu-cmd with redirection, backgrounding, and PID capture |
|---|
| 170 | +sed -e 's/$/ 2>\&1 \&/' < $resdir/qemu-cmd > $T/qemu-cmd |
|---|
| 171 | +echo 'echo $! > $resdir/qemu_pid' >> $T/qemu-cmd |
|---|
| 172 | + |
|---|
| 173 | +# In case qemu refuses to run... |
|---|
| 180 | 174 | echo "NOTE: $QEMU either did not run or was interactive" > $resdir/console.log |
|---|
| 181 | | -echo $QEMU $qemu_args -m $TORTURE_QEMU_MEM -kernel $KERNEL -append \"$qemu_append $boot_args\" > $resdir/qemu-cmd |
|---|
| 182 | | -( $QEMU $qemu_args -m $TORTURE_QEMU_MEM -kernel $KERNEL -append "$qemu_append $boot_args"& echo $! > $resdir/qemu_pid; wait `cat $resdir/qemu_pid`; echo $? > $resdir/qemu-retval ) & |
|---|
| 175 | + |
|---|
| 176 | +# Attempt to run qemu |
|---|
| 177 | +( . $T/qemu-cmd; wait `cat $resdir/qemu_pid`; echo $? > $resdir/qemu-retval ) & |
|---|
| 183 | 178 | commandcompleted=0 |
|---|
| 184 | | -sleep 10 # Give qemu's pid a chance to reach the file |
|---|
| 185 | | -if test -s "$resdir/qemu_pid" |
|---|
| 179 | +if test -z "$TORTURE_KCONFIG_GDB_ARG" |
|---|
| 186 | 180 | then |
|---|
| 187 | | - qemu_pid=`cat "$resdir/qemu_pid"` |
|---|
| 188 | | - echo Monitoring qemu job at pid $qemu_pid |
|---|
| 189 | | -else |
|---|
| 190 | | - qemu_pid="" |
|---|
| 191 | | - echo Monitoring qemu job at yet-as-unknown pid |
|---|
| 181 | + sleep 10 # Give qemu's pid a chance to reach the file |
|---|
| 182 | + if test -s "$resdir/qemu_pid" |
|---|
| 183 | + then |
|---|
| 184 | + qemu_pid=`cat "$resdir/qemu_pid"` |
|---|
| 185 | + echo Monitoring qemu job at pid $qemu_pid |
|---|
| 186 | + else |
|---|
| 187 | + qemu_pid="" |
|---|
| 188 | + echo Monitoring qemu job at yet-as-unknown pid |
|---|
| 189 | + fi |
|---|
| 190 | +fi |
|---|
| 191 | +if test -n "$TORTURE_KCONFIG_GDB_ARG" |
|---|
| 192 | +then |
|---|
| 193 | + echo Waiting for you to attach a debug session, for example: > /dev/tty |
|---|
| 194 | + echo " gdb $base_resdir/vmlinux" > /dev/tty |
|---|
| 195 | + echo 'After symbols load and the "(gdb)" prompt appears:' > /dev/tty |
|---|
| 196 | + echo " target remote :1234" > /dev/tty |
|---|
| 197 | + echo " continue" > /dev/tty |
|---|
| 198 | + kstarttime=`gawk 'BEGIN { print systime() }' < /dev/null` |
|---|
| 192 | 199 | fi |
|---|
| 193 | 200 | while : |
|---|
| 194 | 201 | do |
|---|
| .. | .. |
|---|
| 196 | 203 | then |
|---|
| 197 | 204 | qemu_pid=`cat "$resdir/qemu_pid"` |
|---|
| 198 | 205 | fi |
|---|
| 199 | | - kruntime=`awk 'BEGIN { print systime() - '"$kstarttime"' }' < /dev/null` |
|---|
| 206 | + kruntime=`gawk 'BEGIN { print systime() - '"$kstarttime"' }' < /dev/null` |
|---|
| 200 | 207 | if test -z "$qemu_pid" || kill -0 "$qemu_pid" > /dev/null 2>&1 |
|---|
| 201 | 208 | then |
|---|
| 202 | | - if test $kruntime -ge $seconds |
|---|
| 209 | + if test $kruntime -ge $seconds -o -f "$TORTURE_STOPFILE" |
|---|
| 203 | 210 | then |
|---|
| 204 | 211 | break; |
|---|
| 205 | 212 | fi |
|---|
| .. | .. |
|---|
| 228 | 235 | fi |
|---|
| 229 | 236 | if test $commandcompleted -eq 0 -a -n "$qemu_pid" |
|---|
| 230 | 237 | then |
|---|
| 231 | | - echo Grace period for qemu job at pid $qemu_pid |
|---|
| 238 | + if ! test -f "$TORTURE_STOPFILE" |
|---|
| 239 | + then |
|---|
| 240 | + echo Grace period for qemu job at pid $qemu_pid |
|---|
| 241 | + fi |
|---|
| 232 | 242 | oldline="`tail $resdir/console.log`" |
|---|
| 233 | 243 | while : |
|---|
| 234 | 244 | do |
|---|
| 235 | | - kruntime=`awk 'BEGIN { print systime() - '"$kstarttime"' }' < /dev/null` |
|---|
| 245 | + if test -f "$TORTURE_STOPFILE" |
|---|
| 246 | + then |
|---|
| 247 | + echo "PID $qemu_pid killed due to run STOP request" >> $resdir/Warnings 2>&1 |
|---|
| 248 | + kill -KILL $qemu_pid |
|---|
| 249 | + break |
|---|
| 250 | + fi |
|---|
| 251 | + kruntime=`gawk 'BEGIN { print systime() - '"$kstarttime"' }' < /dev/null` |
|---|
| 236 | 252 | if kill -0 $qemu_pid > /dev/null 2>&1 |
|---|
| 237 | 253 | then |
|---|
| 238 | 254 | : |
|---|
| .. | .. |
|---|
| 246 | 262 | must_continue=yes |
|---|
| 247 | 263 | fi |
|---|
| 248 | 264 | last_ts="`tail $resdir/console.log | grep '^\[ *[0-9]\+\.[0-9]\+]' | tail -1 | sed -e 's/^\[ *//' -e 's/\..*$//'`" |
|---|
| 249 | | - if test -z "last_ts" |
|---|
| 265 | + if test -z "$last_ts" |
|---|
| 250 | 266 | then |
|---|
| 251 | 267 | last_ts=0 |
|---|
| 252 | 268 | fi |
|---|