1#!/bin/bash
2#
3# Run a series of 14 tests under KVM.  These are not particularly
4# well-selected or well-tuned, but are the current set.  Run from the
5# top level of the source tree.
6#
7# Edit the definitions below to set the locations of the various directories,
8# as well as the test duration.
9#
10# Usage: sh kvm.sh [ options ]
11#
12# This program is free software; you can redistribute it and/or modify
13# it under the terms of the GNU General Public License as published by
14# the Free Software Foundation; either version 2 of the License, or
15# (at your option) any later version.
16#
17# This program is distributed in the hope that it will be useful,
18# but WITHOUT ANY WARRANTY; without even the implied warranty of
19# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20# GNU General Public License for more details.
21#
22# You should have received a copy of the GNU General Public License
23# along with this program; if not, you can access it online at
24# http://www.gnu.org/licenses/gpl-2.0.html.
25#
26# Copyright (C) IBM Corporation, 2011
27#
28# Authors: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
29
30scriptname=$0
31args="$*"
32
33T=/tmp/kvm.sh.$$
34trap 'rm -rf $T' 0
35mkdir $T
36
37dur=30
38KVM="`pwd`/tools/testing/selftests/rcutorture"; export KVM
39PATH=${KVM}/bin:$PATH; export PATH
40builddir="${KVM}/b1"
41RCU_INITRD="$KVM/initrd"; export RCU_INITRD
42RCU_KMAKE_ARG=""; export RCU_KMAKE_ARG
43resdir=""
44configs=""
45cpus=0
46ds=`date +%Y.%m.%d-%H:%M:%S`
47kversion=""
48
49. functions.sh
50
51usage () {
52	echo "Usage: $scriptname optional arguments:"
53	echo "       --bootargs kernel-boot-arguments"
54	echo "       --builddir absolute-pathname"
55	echo "       --buildonly"
56	echo "       --configs \"config-file list\""
57	echo "       --cpus N"
58	echo "       --datestamp string"
59	echo "       --duration minutes"
60	echo "       --interactive"
61	echo "       --kmake-arg kernel-make-arguments"
62	echo "       --kversion vN.NN"
63	echo "       --mac nn:nn:nn:nn:nn:nn"
64	echo "       --no-initrd"
65	echo "       --qemu-args qemu-system-..."
66	echo "       --qemu-cmd qemu-system-..."
67	echo "       --results absolute-pathname"
68	echo "       --relbuilddir relative-pathname"
69	exit 1
70}
71
72while test $# -gt 0
73do
74	case "$1" in
75	--bootargs)
76		checkarg --bootargs "(list of kernel boot arguments)" "$#" "$2" '.*' '^--'
77		RCU_BOOTARGS="$2"
78		shift
79		;;
80	--builddir)
81		checkarg --builddir "(absolute pathname)" "$#" "$2" '^/' '^error'
82		builddir=$2
83		gotbuilddir=1
84		shift
85		;;
86	--buildonly)
87		RCU_BUILDONLY=1; export RCU_BUILDONLY
88		;;
89	--configs)
90		checkarg --configs "(list of config files)" "$#" "$2" '^[^/]*$' '^--'
91		configs="$2"
92		shift
93		;;
94	--cpus)
95		checkarg --cpus "(number)" "$#" "$2" '^[0-9]*$' '^--'
96		cpus=$2
97		shift
98		;;
99	--datestamp)
100		checkarg --datestamp "(relative pathname)" "$#" "$2" '^[^/]*$' '^--'
101		ds=$2
102		shift
103		;;
104	--duration)
105		checkarg --duration "(minutes)" $# "$2" '^[0-9]*$' '^error'
106		dur=$2
107		shift
108		;;
109	--interactive)
110		RCU_QEMU_INTERACTIVE=1; export RCU_QEMU_INTERACTIVE
111		;;
112	--kmake-arg)
113		checkarg --kmake-arg "(kernel make arguments)" $# "$2" '.*' '^error$'
114		RCU_KMAKE_ARG="$2"; export RCU_KMAKE_ARG
115		shift
116		;;
117	--kversion)
118		checkarg --kversion "(kernel version)" $# "$2" '^v[0-9.]*$' '^error'
119		kversion=$2
120		shift
121		;;
122	--mac)
123		checkarg --mac "(MAC address)" $# "$2" '^\([0-9a-fA-F]\{2\}:\)\{5\}[0-9a-fA-F]\{2\}$' error
124		RCU_QEMU_MAC=$2; export RCU_QEMU_MAC
125		shift
126		;;
127	--no-initrd)
128		RCU_INITRD=""; export RCU_INITRD
129		;;
130	--qemu-args)
131		checkarg --qemu-args "-qemu args" $# "$2" '^-' '^error'
132		RCU_QEMU_ARG="$2"
133		shift
134		;;
135	--qemu-cmd)
136		checkarg --qemu-cmd "(qemu-system-...)" $# "$2" 'qemu-system-' '^--'
137		RCU_QEMU_CMD="$2"; export RCU_QEMU_CMD
138		shift
139		;;
140	--relbuilddir)
141		checkarg --relbuilddir "(relative pathname)" "$#" "$2" '^[^/]*$' '^--'
142		relbuilddir=$2
143		gotrelbuilddir=1
144		builddir=${KVM}/${relbuilddir}
145		shift
146		;;
147	--results)
148		checkarg --results "(absolute pathname)" "$#" "$2" '^/' '^error'
149		resdir=$2
150		shift
151		;;
152	*)
153		echo Unknown argument $1
154		usage
155		;;
156	esac
157	shift
158done
159
160CONFIGFRAG=${KVM}/configs; export CONFIGFRAG
161KVPATH=${CONFIGFRAG}/$kversion; export KVPATH
162
163if test -z "$configs"
164then
165	configs="`cat $CONFIGFRAG/$kversion/CFLIST`"
166fi
167
168if test -z "$resdir"
169then
170	resdir=$KVM/res
171	if ! test -e $resdir
172	then
173		mkdir $resdir || :
174	fi
175else
176	if ! test -e $resdir
177	then
178		mkdir -p "$resdir" || :
179	fi
180fi
181mkdir $resdir/$ds
182echo Results directory: $resdir/$ds
183touch $resdir/$ds/log
184echo $scriptname $args
185echo $scriptname $args >> $resdir/$ds/log
186
187pwd > $resdir/$ds/testid.txt
188if test -d .git
189then
190	git status >> $resdir/$ds/testid.txt
191	git rev-parse HEAD >> $resdir/$ds/testid.txt
192fi
193
194touch $T/cfgcpu
195for CF in $configs
196do
197	if test -f "$CONFIGFRAG/$kversion/$CF"
198	then
199		echo $CF `configNR_CPUS.sh $CONFIGFRAG/$kversion/$CF` >> $T/cfgcpu
200	else
201		echo "The --configs file $CF does not exist, terminating."
202		exit 1
203	fi
204done
205sort -k2nr $T/cfgcpu > $T/cfgcpu.sort
206
207awk < $T/cfgcpu.sort \
208	-v CONFIGDIR="$CONFIGFRAG/$kversion/" \
209	-v KVM="$KVM" \
210	-v ncpus=$cpus \
211	-v rd=$resdir/$ds/ \
212	-v dur=$dur \
213	-v RCU_QEMU_ARG=$RCU_QEMU_ARG \
214	-v RCU_BOOTARGS=$RCU_BOOTARGS \
215'BEGIN {
216	i = 0;
217}
218
219{
220	cf[i] = $1;
221	cpus[i] = $2;
222	i++;
223}
224
225function dump(first, pastlast)
226{
227	print "echo ----start batch----"
228	jn=1
229	for (j = first; j < pastlast; j++) {
230		builddir=KVM "/b" jn
231		print "echo ", cf[j], cpus[j] ": Starting build."
232		print "rm -f " builddir ".*"
233		print "touch " builddir ".wait"
234		print "mkdir " builddir " || :"
235		if (cfrep[cf[j]] == "") {
236			cfr[j] = cf[j];
237			cfrep[cf[j]] = 1;
238		} else {
239			cfrep[cf[j]]++;
240			cfr[j] = cf[j] "." cfrep[cf[j]];
241		}
242		print "mkdir " rd cfr[j] " || :";
243		print "kvm-test-1-rcu.sh " CONFIGDIR cf[j], builddir, rd cfr[j], dur " \"" RCU_QEMU_ARG "\" \"" RCU_BOOTARGS "\" > " builddir ".out 2>&1 &"
244		print "echo ", cf[j], cpus[j] ": Waiting for build to complete."
245		print "while test -f " builddir ".wait"
246		print "do"
247		print "\tsleep 1"
248		print "done"
249		print "echo ", cf[j], cpus[j] ": Build complete."
250		jn++;
251	}
252	k = first
253	for (j = 1; j < jn; j++) {
254		builddir=KVM "/b" j
255		print "rm -f " builddir ".ready"
256		print "echo ----", cf[k], cpus[k] ": Starting kernel"
257		k++;
258	}
259	print "wait"
260	print "echo ---- All kernel runs complete"
261	k = first
262	for (j = 1; j < jn; j++) {
263		builddir=KVM "/b" j
264		print "echo ----", cf[k], cpus[k] ": Build/run results:"
265		print "cat " builddir ".out"
266		k++;
267	}
268}
269
270END {
271	njobs = i;
272	nc = ncpus;
273	first = 0;
274	for (i = 0; i < njobs; i++) {
275		if (ncpus == 0) {
276			dump(i, i + 1);
277			first = i;
278		} else if (nc < cpus[i] && i != 0) {
279			dump(first, i);
280			first = i;
281			nc = ncpus;
282		}
283		nc -= cpus[i];
284	}
285	if (ncpus != 0)
286		dump(first, i);
287}' > $T/script
288
289sh $T/script
290
291# Tracing: trace_event=rcu:rcu_grace_period,rcu:rcu_future_grace_period,rcu:rcu_grace_period_init,rcu:rcu_nocb_wake,rcu:rcu_preempt_task,rcu:rcu_unlock_preempted_task,rcu:rcu_quiescent_state_report,rcu:rcu_fqs,rcu:rcu_callback,rcu:rcu_kfree_callback,rcu:rcu_batch_start,rcu:rcu_invoke_callback,rcu:rcu_invoke_kfree_callback,rcu:rcu_batch_end,rcu:rcu_torture_read,rcu:rcu_barrier
292
293echo " --- `date` Test summary:"
294kvm-recheck.sh $resdir/$ds
295