opcontrol revision 8cfa702f803c5ef6a2b062a489a1b2cf66b45b5e
1#!/bin/sh
2#
3# opcontrol is a script to control OProfile
4# opcontrol --help and opcontrol --list-events have info
5#
6# Copyright 2002
7# Read the file COPYING
8#
9# Authors: John Levon, Philippe Elie, Will Cohen, Jens Wilke, Daniel Hansel
10#
11# Copyright IBM Corporation 2007
12#
13# NOTE: This script should be as shell independent as possible
14
15SYSCTL=do_sysctl
16
17# A replacement function for the sysctl (procps package) utility which is
18# missing on some distribution (e.g. slack 7.0).
19# Handles only the -w option of sysctl.
20do_sysctl()
21{
22	if test "$1" != "-w"; then
23		echo "$0 unknown sysctl option" >&2
24		exit 1
25	fi
26
27	shift
28
29	arg=`echo $1 | awk -F= '{print $1}'`
30	val=`echo $1 | awk -F= '{print $2}'`
31
32	dev_name=`echo $arg | tr . /`
33
34	if test ! -f /proc/sys/$dev_name; then
35		echo "/proc/sys/$dev_name does not exist or is not a regular file" >&2
36		exit 1
37	fi
38	echo $val > /proc/sys/$dev_name
39}
40
41
42# check value is set
43error_if_empty()
44{
45	if test -z "$2"; then
46		echo "No value given for option $1" >&2
47		do_help
48		exit 1
49	fi
50}
51
52
53# rm_device arguments $1=file_name
54rm_device()
55{
56	if test -c "$1"; then
57		vecho "Removing $1"
58		rm "$1"
59	fi
60}
61
62
63# create_device arguments $1=file_name $2=MAJOR_NR $3=MINOR_NR
64create_device()
65{
66	vecho "Doing mknod $1"
67	mknod "$1" c $2 $3
68	if test "$?" != "0"; then
69		echo "Couldn't mknod $1" >&2
70		exit 1
71	fi
72	chmod 700 "$1"
73}
74
75
76move_and_remove()
77{
78	if test -e $1; then
79		mv $1 $SAMPLES_DIR/.tmp_reset.$$
80		rm -rf $SAMPLES_DIR/.tmp_reset.$$
81	fi
82}
83
84
85# verbose echo
86vecho()
87{
88	if test -n "$VERBOSE"; then
89		echo $@
90	fi
91}
92
93
94is_tool_available()
95{
96	if which $1 &>/dev/null; then
97		if test -x `which $1`; then
98			return 1
99		fi
100	fi
101
102	return 0
103}
104
105
106# print help message
107do_help()
108{
109    cat >&2 <<EOF
110opcontrol: usage:
111   -l/--list-events list event types and unit masks
112   -?/--help        this message
113   -v/--version     show version
114   --init           loads the oprofile module and oprofilefs
115   --setup          give setup arguments (may be omitted)
116   --status         show configuration
117   --start-daemon   start daemon without starting profiling
118   -s/--start       start data collection
119   -d/--dump        flush the collected profiling data
120   -t/--stop        stop data collection
121   -h/--shutdown    stop data collection and kill daemon
122   -V/--verbose[=all,sfile,arcs,samples,module,misc,ext]
123                    be verbose in the daemon log
124   --reset          clears out data from current session
125   --save=name      save data from current session to session_name
126   --deinit         unload the oprofile module and oprofilefs
127
128   -e/--event=eventspec
129
130      Choose an event. May be specified multiple times. Of the form
131      "default" or "name:count:unitmask:kernel:user", where :
132
133      name:     event name, e.g. CPU_CLK_UNHALTED or RTC_INTERRUPTS
134      count:    reset counter value e.g. 100000
135      unitmask: hardware unit mask e.g. 0x0f
136      kernel:   whether to profile kernel: 0 or 1
137      user:     whether to profile userspace: 0 or 1
138
139   -p/--separate=type,[types]
140
141       Separate profiles as follows :
142
143       none:     no profile separation
144       library:  separate shared library profiles per-application
145       kernel:   same as library, plus kernel profiles
146       thread:   per-thread/process profiles
147       cpu:      per CPU profiles
148       all:      all of the above
149
150   -c/--callgraph=#depth         enable callgraph sample collection with a maximum depth.
151                                 Use 0 to disable callgraph profiling.
152   --session-dir=dir             place sample database in dir instead of
153                                 default location (/var/lib/oprofile)
154   -i/--image=name[,names]       list of binaries to profile (default is "all")
155   --vmlinux=file                vmlinux kernel image
156   --no-vmlinux                  no kernel image (vmlinux) available
157   --kernel-range=start,end      kernel range vma address in hexadecimal
158   --buffer-size=num             kernel buffer size in sample units
159   --buffer-watershed            kernel buffer watershed in sample units (2.6 only=
160   --cpu-buffer-size=num         per-cpu buffer size in units (2.6 only)
161   --note-table-size             kernel notes buffer size in notes units (2.4 only)
162
163   --xen                         Xen image (for Xen only)
164   --active-domains=<list>       List of domains in profiling session (for Xen only)
165                                 (list contains domain ids separated by commas)
166EOF
167}
168
169
170# load the module and mount oprofilefs
171load_module_26()
172{
173	grep oprofilefs /proc/filesystems >/dev/null
174	if test "$?" -ne 0; then
175		modprobe oprofile
176		if test "$?" != "0"; then
177			# couldn't load the module
178			return
179		fi
180		grep oprofile /proc/modules >/dev/null
181		if test "$?" != "0"; then
182			# didn't find module
183			return
184		fi
185		grep oprofilefs /proc/filesystems >/dev/null
186		if test "$?" -ne 0; then
187			# filesystem still not around
188			return
189		fi
190	fi
191	mkdir /dev/oprofile >/dev/null 2>&1
192	grep oprofilefs /etc/mtab >/dev/null
193	if test "$?" -ne 0; then
194		mount -t oprofilefs nodev /dev/oprofile >/dev/null
195	fi
196	KERNEL_SUPPORT=yes
197	OPROFILE_AVAILABLE=yes
198}
199
200
201load_module_24()
202{
203	grep oprof /proc/devices >/dev/null
204	if test "$?" -ne 0; then
205		modprobe oprofile
206		if test "$?" != "0"; then
207			# couldn't load a module
208			return
209		fi
210		grep oprofile /proc/modules >/dev/null
211		if test "$?" != "0"; then
212			# didn't find module
213			return
214		fi
215	fi
216	KERNEL_SUPPORT=no
217	OPROFILE_AVAILABLE=yes
218}
219
220
221load_module()
222{
223	OPROFILE_AVAILABLE=no
224	load_module_26
225	if test "$OPROFILE_AVAILABLE" != "yes"; then
226		load_module_24
227	fi
228	if test "$OPROFILE_AVAILABLE" != "yes"; then
229		echo "Kernel doesn't support oprofile" >&2
230		exit 1
231	fi
232}
233
234# setup variables related to path or daemon. Set vars according to following
235# relationship: command-line-option > config-file-settings > defaults.
236# Note that upon entry SESSION_DIR may be set by command-line option.
237do_init_daemon_vars()
238{
239	# load settings from config file, keeping command-line value
240	# of SESSION_DIR if necessary.
241	if test -n "$SESSION_DIR"; then
242		SAVED=$SESSION_DIR
243	fi
244	do_load_setup
245	if test -n "$SAVED"; then
246		SESSION_DIR=$SAVED
247	fi
248
249	# daemon parameters (as in op_config.h).  Note that we preserve
250	# any previous value of SESSION_DIR
251	if test -z "$SESSION_DIR"; then
252		SESSION_DIR="/var/lib/oprofile"
253	fi
254	LOCK_FILE="$SESSION_DIR/lock"
255	SAMPLES_DIR="$SESSION_DIR/samples"
256	LOG_FILE="$SAMPLES_DIR/oprofiled.log"
257	CURRENT_SAMPLES_DIR="$SAMPLES_DIR/current"
258}
259
260
261# pick the appropriate device mount based on kernel
262decide_oprofile_device_mount()
263{
264	if test "$KERNEL_SUPPORT" = "yes"; then
265		MOUNT="/dev/oprofile"
266	else
267		MOUNT="/proc/sys/dev/oprofile"
268	fi
269}
270
271
272# pick the appropriate locations device for oprofile based on kernel
273decide_oprofile_device()
274{
275	if test "$KERNEL_SUPPORT" = "yes"; then
276		DEVICE_FILE="$MOUNT/buffer"
277	else
278		DEVICE_FILE="$SESSION_DIR/opdev"
279		NOTE_DEVICE_FILE="$SESSION_DIR/opnotedev"
280		HASH_MAP_DEVICE_FILE="$SESSION_DIR/ophashmapdev"
281	fi
282}
283
284# initialise parameters
285do_init()
286{
287	# for these three buffer size == 0 means use the default value
288	# hard-coded in op_user.h
289	BUF_SIZE=0
290	BUF_WATERSHED=0
291	CPU_BUF_SIZE=0
292	NOTE_SIZE=0
293	VMLINUX=
294	XENIMAGE="none"
295	VERBOSE=""
296	SEPARATE_LIB=0
297	SEPARATE_KERNEL=0
298	SEPARATE_THREAD=0
299	SEPARATE_CPU=0
300	CALLGRAPH=0
301	IBS_FETCH_EVENTS=""
302	IBS_FETCH_COUNT=0
303	IBS_FETCH_UNITMASK=0
304	IBS_OP_EVENTS=""
305	IBS_OP_COUNT=0
306	IBS_OP_UNITMASK=0
307
308	OPROFILED="$OPDIR/oprofiled"
309
310	# location for daemon setup information
311	SETUP_DIR="/root/.oprofile"
312	SETUP_FILE="$SETUP_DIR/daemonrc"
313
314	# initialize daemon vars
315	decide_oprofile_device_mount
316	CPUTYPE=`cat $MOUNT/cpu_type`
317	OP_COUNTERS=`ls $MOUNT/ | grep "^[0-9]\+\$" | tr "\n" " "`
318	NR_CHOSEN=0
319
320	do_init_daemon_vars
321	decide_oprofile_device
322
323	DEFAULT_EVENT=`$OPHELP --get-default-event`
324
325	IS_TIMER=0
326	IS_PERFMON=0
327	if test "$CPUTYPE" = "timer"; then
328		IS_TIMER=1
329	else
330		case "$CPUTYPE" in
331			ia64/*)
332				IS_PERFMON=$KERNEL_SUPPORT
333				;;
334		esac
335	fi
336}
337
338
339create_dir()
340{
341	if test ! -d "$1"; then
342		mkdir -p "$1"
343		if test "$?" != "0"; then
344			echo "Couldn't mkdir -p $1" >&2
345			exit 1
346		fi
347		chmod 755 "$1"
348	fi
349}
350
351get_event()
352{
353	GOTEVENT=`eval "echo \\$CHOSEN_EVENTS_$1"`
354}
355
356set_event()
357{
358	eval "CHOSEN_EVENTS_$1=$2"
359}
360
361
362# save all the setup related information
363do_save_setup()
364{
365	create_dir "$SETUP_DIR"
366
367	touch $SETUP_FILE
368	chmod 644 $SETUP_FILE
369	>$SETUP_FILE
370
371	echo "SESSION_DIR=$SESSION_DIR" >>$SETUP_FILE
372
373	if test "$NR_CHOSEN" != "0"; then
374		for f in `seq 0 $((NR_CHOSEN - 1))`; do
375			get_event $f
376			echo "CHOSEN_EVENTS_${f}=$GOTEVENT" >>$SETUP_FILE
377		done
378	fi
379
380	echo "NR_CHOSEN=$NR_CHOSEN" >>$SETUP_FILE
381
382	echo "SEPARATE_LIB=$SEPARATE_LIB" >> $SETUP_FILE
383	echo "SEPARATE_KERNEL=$SEPARATE_KERNEL" >> $SETUP_FILE
384	echo "SEPARATE_THREAD=$SEPARATE_THREAD" >> $SETUP_FILE
385	echo "SEPARATE_CPU=$SEPARATE_CPU" >> $SETUP_FILE
386	echo "VMLINUX=$VMLINUX" >> $SETUP_FILE
387	echo "IMAGE_FILTER=$IMAGE_FILTER" >> $SETUP_FILE
388	# write the actual information to file
389	if test "$BUF_SIZE" != "0"; then
390		echo "BUF_SIZE=$BUF_SIZE" >> $SETUP_FILE
391	fi
392	if test "$BUF_WATERSHED" != "0"; then
393		echo "BUF_WATERSHED=$BUF_WATERSHED" >> $SETUP_FILE
394	fi
395	if test "$KERNEL_SUPPORT" = "yes"; then
396		echo "CPU_BUF_SIZE=$CPU_BUF_SIZE" >> $SETUP_FILE
397	fi
398	if test "$KERNEL_SUPPORT" != "yes"; then
399		echo "NOTE_SIZE=$NOTE_SIZE" >> $SETUP_FILE
400	fi
401	echo "CALLGRAPH=$CALLGRAPH" >> $SETUP_FILE
402	if test "$KERNEL_RANGE"; then
403		echo "KERNEL_RANGE=$KERNEL_RANGE" >> $SETUP_FILE
404	fi
405	echo "XENIMAGE=$XENIMAGE" >> $SETUP_FILE
406	if test "$XEN_RANGE"; then
407		echo "XEN_RANGE=$XEN_RANGE" >> $SETUP_FILE
408	fi
409}
410
411
412# reload all the setup-related information
413do_load_setup()
414{
415	if test -f "$SETUP_FILE"; then
416		# load the actual information from file
417		# FIXME this is insecure, arbitrary commands could be added to
418		# $SETUP_FILE and be executed as root
419		. $SETUP_FILE
420	fi
421}
422
423
424check_valid_args()
425{
426	if test -z "$VMLINUX"; then
427		echo "No vmlinux file specified. You must specify the correct vmlinux file, e.g." >&2
428		echo "opcontrol --vmlinux=/path/to/vmlinux" >&2
429		echo "If you do not have a vmlinux file, use " >&2
430		echo "opcontrol --no-vmlinux" >&2
431		echo "Enter opcontrol --help for full options" >&2
432		exit 1
433	fi
434
435	if test -f "$VMLINUX"; then
436		return
437	fi
438
439	if test "$VMLINUX" = "none"; then
440		return
441	fi
442
443	echo "The specified vmlinux file \"$VMLINUX\" doesn't exist." >&2
444	exit 1
445
446# similar check for Xen image
447	if test -f "$XENIMAGE"; then
448		return
449	fi
450
451	if test "$XENIMAGE" = "none"; then
452		return
453	fi
454
455	echo "The specified XenImage file \"$XENIMAGE\" does not exist." >&2
456	exit 1
457}
458
459
460# get start and end points of a file image (linux kernel or xen)
461# get_image_range parameter: $1=type_of_image (linux or xen)
462get_image_range()
463{
464	if test "$1" = "xen"; then
465		if test ! -z "$XEN_RANGE"; then
466			return;
467		fi
468		FILE_IMAGE="$XENIMAGE"
469	else
470		if test ! -z "$KERNEL_RANGE"; then
471			return;
472		fi
473		FILE_IMAGE="$VMLINUX"
474	fi
475
476	if test "$FILE_IMAGE" = "none"; then
477		return;
478	fi
479
480	if is_tool_available objdump; then
481		echo "objdump is not installed on this system, use opcontrol --kernel-range=start,end or opcontrol --xen-range= or install objdump"
482		exit 1
483	fi
484
485	# start at the start of .text, and end at _etext
486	range_info=`objdump -h $FILE_IMAGE 2>/dev/null | grep " .text "`
487	tmp1=`echo $range_info | awk '{print $4}'`
488	tmp2=`objdump -t $FILE_IMAGE 2>/dev/null | grep "_etext$" | awk '{ print $1 }'`
489
490	if test -z "$tmp1" -o -z "$tmp2"; then
491		echo "The specified file $FILE_IMAGE does not seem to be valid" >&2
492		echo "Make sure you are using the non-compressed image file (e.g. vmlinux not vmlinuz)" >&2
493		vecho "found start as \"$tmp1\", end as \"$tmp2\"" >&2
494		exit 1
495	fi
496
497	if test "$1" = "xen"; then
498		XEN_RANGE="`echo $tmp1`,`echo $tmp2`"
499		vecho "XEN_RANGE $XEN_RANGE"
500	else
501		KERNEL_RANGE="`echo $tmp1`,`echo $tmp2`"
502		vecho "KERNEL_RANGE $KERNEL_RANGE"
503	fi
504}
505
506
507# validate --separate= parameters. This function is called with IFS=,
508# so on each argument is splitted
509validate_separate_args()
510{
511	error_if_empty $1 $2	# we need at least one argument
512	local i=1
513	SEPARATE_LIB=0
514	SEPARATE_KERNEL=0
515	SEPARATE_THREAD=0
516	SEPARATE_CPU=0
517	while [ "$i" -lt "$#" ]; do
518		shift
519		case "$1" in
520			lib|library)
521				SEPARATE_LIB=1
522				;;
523			kernel)
524				# first implied by second
525				SEPARATE_LIB=1
526				SEPARATE_KERNEL=1
527				;;
528			thread)
529				SEPARATE_THREAD=1
530				;;
531			cpu)
532				SEPARATE_CPU=1
533				;;
534			all)
535				SEPARATE_LIB=1
536				SEPARATE_KERNEL=1
537				SEPARATE_THREAD=1
538				SEPARATE_CPU=1
539				;;
540			none)
541				SEPARATE_LIB=0
542				SEPARATE_KERNEL=0
543				SEPARATE_THREAD=0
544				SEPARATE_CPU=0
545				;;
546			*)
547				echo "invalid --separate= argument: $1"
548				exit 1
549		esac
550	done
551}
552
553
554# check the counters make sense, and resolve the hardware allocation
555verify_counters()
556{
557	if test "$IS_TIMER" = 1; then
558		if test "$NR_CHOSEN" != 0; then
559			echo "You cannot specify any performance counter events" >&2
560			echo "because OProfile is in timer mode." >&2
561			exit 1
562		fi
563		return
564	fi
565
566	OPHELP_ARGS=
567
568	if test "$NR_CHOSEN" != 0; then
569		for f in `seq 0 $((NR_CHOSEN - 1))`; do
570			get_event $f
571			if test "$GOTEVENT" != ""; then
572				verify_ibs $GOTEVENT
573				OPHELP_ARGS="$OPHELP_ARGS $GOTEVENT"
574			fi
575		done
576
577		if test ! -z "$OPHELP_ARGS" ; then
578			HW_CTRS=`$OPHELP --check-events $OPHELP_ARGS --callgraph=$CALLGRAPH`
579			if test "$?" != 0; then
580				exit 1
581			fi
582		fi
583	fi
584}
585
586
587# setup any needed default value in chosen events
588normalise_events()
589{
590	if test "$NR_CHOSEN" -le 0 || test "$IS_TIMER" = 1; then
591		return
592	fi
593
594	for f in `seq 0 $((NR_CHOSEN - 1))`; do
595		get_event $f
596		if test "$GOTEVENT" != ""; then
597			EVENT=`echo $GOTEVENT | awk -F: '{print $1}'`
598			EVENT_VAL=`$OPHELP $EVENT`
599			if test "$?" != 0; then
600				exit 1
601			fi
602			COUNT=`echo $GOTEVENT | awk -F: '{print $2}'`
603			UNIT_MASK=`echo $GOTEVENT | awk -F: '{print $3}'`
604			KERNEL=`echo $GOTEVENT | awk -F: '{print $4}'`
605			USER=`echo $GOTEVENT | awk -F: '{print $5}'`
606			if test -z "$UNIT_MASK"; then
607				TMPEVENT="$EVENT:$COUNT"
608				UNIT_MASK=`$OPHELP --unit-mask $TMPEVENT`
609				if test "$?" != 0; then
610					exit 1
611				fi
612			fi
613			if test -z "$KERNEL"; then
614				KERNEL=1
615			fi
616			if test -z "$USER"; then
617				USER=1
618			fi
619
620			set_event $f "$EVENT:$COUNT:$UNIT_MASK:$KERNEL:$USER"
621		fi
622	done
623}
624
625
626# get and check specified options
627do_options()
628{
629	EXCLUSIVE_ARGC=0
630	SETUP=no
631	NEED_SETUP=no
632	SEEN_EVENT=0
633
634	# note: default settings have already been loaded
635
636	while [ "$#" -ne 0 ]
637	do
638		arg=`printf %s $1 | awk -F= '{print $1}'`
639		val=`printf %s $1 | awk -F= '{print $2}'`
640		shift
641		if test -z "$val"; then
642			local possibleval=$1
643			printf %s $1 "$possibleval" | grep ^- >/dev/null 2>&1
644			if test "$?" != "0"; then
645				val=$possibleval
646				if [ "$#" -ge 1 ]; then
647					shift
648				fi
649			fi
650		fi
651
652		case "$arg" in
653
654			--init)
655				# this is already done in load_module
656				# because need to know the processor type
657				# and number of registers
658				INIT=yes;
659				EXCLUSIVE_ARGC=`expr $EXCLUSIVE_ARGC + 1`
660				EXCLUSIVE_ARGV="$arg"
661				;;
662
663			--setup)
664				SETUP=yes
665				;;
666
667			--start-daemon)
668				if test "$KERNEL_SUPPORT" != "yes"; then
669					echo "$arg unsupported. use \"--start\"" >&2
670					exit 1
671				fi
672				START_DAEMON=yes
673				EXCLUSIVE_ARGC=`expr $EXCLUSIVE_ARGC + 1`
674				EXCLUSIVE_ARGV="$arg"
675				;;
676
677			-s|--start)
678				START=yes
679				EXCLUSIVE_ARGC=`expr $EXCLUSIVE_ARGC + 1`
680				EXCLUSIVE_ARGV="$arg"
681				;;
682
683			-d|--dump)
684				DUMP=yes
685				ONLY_DUMP=yes
686				EXCLUSIVE_ARGC=`expr $EXCLUSIVE_ARGC + 1`
687				EXCLUSIVE_ARGV="$arg"
688				;;
689
690			-t|--stop)
691				if test "$KERNEL_SUPPORT" != "yes"; then
692					echo "$arg unsupported. use \"--shutdown\"" >&2
693					exit 1
694				fi
695				DUMP=yes
696				STOP=yes
697				EXCLUSIVE_ARGC=`expr $EXCLUSIVE_ARGC + 1`
698				EXCLUSIVE_ARGV="$arg"
699				;;
700
701			-h|--shutdown)
702				DUMP=yes
703				STOP=yes
704				KILL_DAEMON=yes
705				EXCLUSIVE_ARGC=`expr $EXCLUSIVE_ARGC + 1`
706				EXCLUSIVE_ARGV="$arg"
707				;;
708
709			--status)
710				STATUS=yes
711				;;
712
713			--reset)
714				DUMP=yes
715				RESET=yes
716				EXCLUSIVE_ARGC=`expr $EXCLUSIVE_ARGC + 1`
717				EXCLUSIVE_ARGV="$arg"
718				;;
719
720			--save)
721				error_if_empty $arg $val
722				DUMP=yes
723				SAVE_SESSION=yes
724				SAVE_NAME=$val
725				EXCLUSIVE_ARGC=`expr $EXCLUSIVE_ARGC + 1`
726				EXCLUSIVE_ARGV="$arg"
727				;;
728
729			--deinit)
730				DUMP=yes
731				test ! -f "$LOCK_FILE" || {
732					STOP=yes
733					KILL_DAEMON=yes
734				}
735				DEINIT=yes
736				EXCLUSIVE_ARGC=`expr $EXCLUSIVE_ARGC + 1`
737				EXCLUSIVE_ARGV="$arg"
738				;;
739
740			# --setup options
741
742			--session-dir)
743				# already processed
744				;;
745			--buffer-size)
746				error_if_empty $arg $val
747				BUF_SIZE=$val
748				DO_SETUP=yes
749				;;
750			--buffer-watershed)
751				if test "$KERNEL_SUPPORT" != "yes"; then
752					echo "$arg unsupported for this kernel version"
753					exit 1
754				fi
755				error_if_empty $arg $val
756				BUF_WATERSHED=$val
757				DO_SETUP=yes
758				;;
759			--cpu-buffer-size)
760				if test "$KERNEL_SUPPORT" != "yes"; then
761					echo "$arg unsupported for this kernel version"
762					exit 1
763				fi
764				error_if_empty $arg $val
765				CPU_BUF_SIZE=$val
766				DO_SETUP=yes
767				;;
768			-e|--event)
769				error_if_empty $arg $val
770				# reset any read-in defaults from daemonrc
771				if test "$SEEN_EVENT" = "0"; then
772					NR_CHOSEN=0
773					SEEN_EVENT=1
774				fi
775				if test "$val" = "default"; then
776					val=$DEFAULT_EVENT
777				fi
778				set_event $NR_CHOSEN "$val"
779				NR_CHOSEN=`expr $NR_CHOSEN + 1`
780				DO_SETUP=yes
781				;;
782			-p|--separate)
783				OLD_IFS=$IFS
784				IFS=,
785				validate_separate_args $arg $val
786				IFS=$OLD_IFS
787				DO_SETUP=yes
788				;;
789			-c|--callgraph)
790				error_if_empty $arg $val
791				if test ! -f $MOUNT/backtrace_depth; then
792					echo "Call-graph profiling unsupported on this kernel/hardware" >&2
793					exit 1
794				fi
795				CALLGRAPH=$val
796				DO_SETUP=yes
797				;;
798			--vmlinux)
799				error_if_empty $arg $val
800				VMLINUX=$val
801				DO_SETUP=yes
802				;;
803			--no-vmlinux)
804				VMLINUX=none
805				DO_SETUP=yes
806				;;
807			--kernel-range)
808				error_if_empty $arg $val
809				KERNEL_RANGE=$val
810				DO_SETUP=yes
811				;;
812			--xen)
813				error_if_empty $arg $val
814				XENIMAGE=$val
815				DO_SETUP=yes
816				;;
817			--active-domains)
818				error_if_empty $arg $val
819				ACTIVE_DOMAINS=$val
820				DO_SETUP=yes
821				;;
822			--note-table-size)
823				error_if_empty $arg $val
824				if test "$KERNEL_SUPPORT" = "yes"; then
825					echo "\"$arg\" meaningless on this kernel" >&2
826					exit 1
827				else
828					NOTE_SIZE=$val
829				fi
830				DO_SETUP=yes
831				;;
832			-i|--image)
833				error_if_empty $arg $val
834				if test "$val" = "all"; then
835					IMAGE_FILTER=
836				else
837					IMAGE_FILTER=$val
838				fi
839				DO_SETUP=yes
840				;;
841
842			-V|--verbose)
843				if test -z "$val"; then
844					VERBOSE="all"
845				else
846					VERBOSE=$val
847				fi
848				;;
849
850			-l|--list-events)
851				EXCLUSIVE_ARGC=`expr $EXCLUSIVE_ARGC + 1`
852				EXCLUSIVE_ARGV="$arg"
853				exec $OPHELP
854				;;
855
856			*)
857				echo "Unknown option \"$arg\". See opcontrol --help" >&2
858				exit 1
859				;;
860		esac
861	done
862
863	normalise_events
864	verify_counters
865
866	# error checking to make sure options make sense
867	if test "$EXCLUSIVE_ARGC" -gt 1; then
868		echo "Option \"$EXCLUSIVE_ARGV\" not valid with other options." >&2
869		exit 1
870	fi
871
872	if test "$SETUP" = "yes" -a "$DO_SETUP" != "yes"; then
873		echo "No options specified for --setup." >&2
874		exit 1
875	fi
876
877	if test -n "$VERBOSE"; then
878		if test "$START" != "yes" -a "$START_DAEMON" != "yes"; then
879			echo "Option --verbose may only be used with --start or --start-daemon" >&2
880			exit 1
881		fi
882	fi
883
884	if test "$DO_SETUP" = "yes"; then
885		SETUP="$DO_SETUP"
886	fi
887
888	if test "$EXCLUSIVE_ARGC" -eq 1 -a "$SETUP" = "yes"; then
889		if test "$EXCLUSIVE_ARGV" != "--start-daemon" -a "$EXCLUSIVE_ARGV" != "--start"; then
890			echo "Option \"--setup\" not valid with \"$EXCLUSIVE_ARGV\"." >&2
891			exit 1
892		fi
893	fi
894
895	vecho "Parameters used:"
896	vecho "SESSION_DIR $SESSION_DIR"
897	vecho "LOCK_FILE   $LOCK_FILE"
898	vecho "SAMPLES_DIR $SAMPLES_DIR"
899	vecho "CURRENT_SAMPLES_DIR $CURRENT_SAMPLES_DIR"
900	vecho "CPUTYPE $CPUTYPE"
901	if test "$BUF_SIZE" != "0"; then
902		vecho "BUF_SIZE $BUF_SIZE"
903	else
904		vecho "BUF_SIZE default value"
905	fi
906	if test "$BUF_WATERSHED" != "0"; then
907		vecho "BUF_WATERSHED $BUF_WATERSHED"
908	else
909		vecho "BUF_WATERSHED default value"
910	fi
911	if test "$KERNEL_SUPPORT" = "yes"; then
912		if test "$CPU_BUF_SIZE" != "0"; then
913			vecho "CPU_BUF_SIZE $CPU_BUF_SIZE"
914		else
915			vecho "CPU_BUF_SIZE default value"
916		fi
917	fi
918
919	vecho "SEPARATE_LIB $SEPARATE_LIB"
920	vecho "SEPARATE_KERNEL $SEPARATE_KERNEL"
921	vecho "SEPARATE_THREAD $SEPARATE_THREAD"
922	vecho "SEPARATE_CPU $SEPARATE_CPU"
923	vecho "CALLGRAPH $CALLGRAPH"
924	vecho "VMLINUX $VMLINUX"
925	vecho "KERNEL_RANGE $KERNEL_RANGE"
926	vecho "XENIMAGE $XENIMAGE"
927	vecho "XEN_RANGE $XEN_RANGE"
928}
929
930
931# stop any existing daemon
932do_stop()
933{
934	if test ! -f "$LOCK_FILE"; then
935		echo "Daemon not running" >&2
936		return
937	fi
938
939	kill -0 `cat $LOCK_FILE` 2>/dev/null
940	if test "$?" -ne 0; then
941		echo "Detected stale lock file. Removing." >&2
942		rm -f "$LOCK_FILE"
943		return
944	fi
945
946	if test $KERNEL_SUPPORT = "yes" \
947	    && test 0 != $(cat /dev/oprofile/enable); then
948		echo "Stopping profiling."
949		echo 0 >/dev/oprofile/enable
950	fi
951	kill -USR2 `cat $LOCK_FILE` 2>/dev/null
952}
953
954
955# kill the daemon process(es)
956do_kill_daemon()
957{
958	if test ! -f "$LOCK_FILE"; then
959		# no error message, do_kill_daemon imply stop and stop already
960		# output "Daemon not running"
961		return
962	fi
963
964	kill -0 `cat $LOCK_FILE` 2>/dev/null
965	if test "$?" -ne 0; then
966		echo "Detected stale lock file. Removing." >&2
967		rm -f "$LOCK_FILE"
968		return
969	fi
970
971	echo "Killing daemon."
972
973	if test $KERNEL_SUPPORT = "yes"; then
974		kill -TERM `cat $LOCK_FILE`
975	else
976		echo 1 >/proc/sys/dev/oprofile/dump_stop
977	fi
978
979	COUNT=0
980	while test -n "`pidof oprofiled`"
981	do
982		sleep 1
983
984		# because oprofiled only sets a variable inside the
985		# signal handler itself, it's possible to miss a
986		# signal just before it goes to sleep waiting for
987		# data from the kernel that never arrives. So we
988		# remind it it needs to die - this works because
989		# the signal will bring oprofiled out of the kernel
990		# back into userspace
991		if test $KERNEL_SUPPORT = "yes"; then
992			pid=`cat $LOCK_FILE 2>/dev/null`
993			kill -TERM "$pid" 2>/dev/null
994		fi
995
996		COUNT=`expr $COUNT + 1`
997
998		# IBS can generate a large number of samples/events.
999		# Therefore, extend the delay before killing
1000		if test "$IBS_FETCH_COUNT" != "0" \
1001		     -o "$IBS_OP_COUNT" != "0" ; then
1002			DELAY_KILL=60
1003		else
1004			DELAY_KILL=15
1005		fi
1006		if test "$COUNT" -eq "$DELAY_KILL"; then
1007			echo "Daemon stuck shutting down; killing !"
1008			kill -9 `cat $LOCK_FILE`
1009		fi
1010	done
1011	sleep 1
1012	# already removed unless we forced the kill
1013	rm -f "$SESSION_DIR/lock"
1014	cp -r /dev/oprofile/stats "$SAMPLES_DIR/current"
1015}
1016
1017
1018rm_devices_24()
1019{
1020	rm_device "$DEVICE_FILE"
1021	rm_device "$NOTE_DEVICE_FILE"
1022	rm_device "$HASH_MAP_DEVICE_FILE"
1023}
1024
1025
1026create_devices_24()
1027{
1028	MAJOR_NR=`grep oprof /proc/devices | awk '{print $1}'`
1029
1030	create_device $DEVICE_FILE $MAJOR_NR 0
1031	create_device $NOTE_DEVICE_FILE $MAJOR_NR 2
1032	create_device $HASH_MAP_DEVICE_FILE $MAJOR_NR 1
1033}
1034
1035# create jitdump directory and remove any old files from
1036# a previous run
1037prep_jitdump() {
1038	local dumpdir=$SESSION_DIR/jitdump
1039	test -d $dumpdir || {
1040		mkdir -p $dumpdir;
1041		chmod 777 $dumpdir;
1042		return;
1043	}
1044	# VMs may already be running when profiling is started, so
1045	# remove only dump files that are not in use
1046	for I in $dumpdir/*; do
1047		test -f $I || continue;
1048		local pid=`basename $I .dump`;
1049		if test -d /proc/$pid; then
1050			local files=`find /proc/$pid/fd -lname $I`;
1051			test -n "$files" && continue;
1052		fi
1053		rm -f $I;
1054	done
1055}
1056
1057# setup and start module
1058do_setup()
1059{
1060	create_dir "$SESSION_DIR"
1061
1062	if test "$KERNEL_SUPPORT" != "yes"; then
1063		rm_devices_24
1064		create_devices_24
1065	fi
1066
1067	create_dir "$CURRENT_SAMPLES_DIR"
1068
1069	prep_jitdump;
1070}
1071
1072
1073# set a sysctl/oprofilefs parameter
1074set_param()
1075{
1076	if test "$KERNEL_SUPPORT" = "yes"; then
1077		echo $2 >$MOUNT/$1
1078	else
1079		$SYSCTL -w dev.oprofile.$1=$2
1080	fi
1081}
1082
1083
1084# set a sysctl/oprofilefs counter parameter
1085set_ctr_param()
1086{
1087	# no such thing for perfmon
1088	if test "$IS_PERFMON" = "yes"; then
1089		return
1090	fi
1091
1092	if test "$KERNEL_SUPPORT" = "yes"; then
1093		if test -e $MOUNT/$1; then
1094			echo $3 >$MOUNT/$1/$2
1095		else
1096			echo -n "Error: counter $1 not available"
1097			if test -e /proc/sys/kernel/nmi_watchdog; then
1098				echo " nmi_watchdog using this resource ? Try:"
1099				echo "opcontrol --deinit"
1100				echo "echo 0 > /proc/sys/kernel/nmi_watchdog"
1101			fi
1102			exit 1
1103		fi
1104	else
1105		$SYSCTL -w dev.oprofile.$1.$2=$3
1106	fi
1107}
1108
1109
1110# returns 1 if $CPUTYPE is a PPC64 variant
1111is_non_cell_ppc64_variant()
1112{
1113	case "$1" in
1114		ppc64/*)
1115			tmp="${1/cell/CELL}"
1116			if test "$1" = "$tmp"; then
1117			#No substituion occurred, so cputype is not cell
1118				return 1
1119			else
1120				return 0
1121			fi
1122			;;
1123		*)
1124			return 0;
1125			;;
1126	esac
1127}
1128
1129
1130# The check_event_mapping_data procedure gives the
1131# opportunity to validate events and enforce any
1132# arch-specific restritions, etc.
1133check_event_mapping_data()
1134{
1135
1136	is_non_cell_ppc64_variant $CPUTYPE
1137	if test $? -ne 0 ; then
1138		# For PPC64 architectures, the values required to program
1139		# MMCRs for the given event are returned along with the event.
1140		# Here we use those values to ensure that all chosen events
1141		# are from the same group.
1142		MMCR0=`echo $EVENT_STR | awk '{print $2}'`
1143		MMCR1=`echo $EVENT_STR | awk '{print $3}'`
1144		MMCRA=`echo $EVENT_STR | awk '{print $4}'`
1145		MMCR0_VAL=`echo $MMCR0 | awk -F: '{print $2}'`
1146		MMCR1_VAL=`echo $MMCR1 | awk -F: '{print $2}'`
1147		MMCRA_VAL=`echo $MMCRA | awk -F: '{print $2}'`
1148
1149		## mmcr0, mmcr1, mmcra are for all ppc64 counters
1150		# Save first event mmcr settings to compare with additional
1151		# events.  All events must have the same mmcrx values i.e. be in
1152		# the same group.  Only one event is assigned per counter,
1153		# hence there will not be a conflict on the counters
1154		if [ "$MMCR0_CK_VAL" = "" ] ; then
1155			MMCR0_CK_VAL=$MMCR0_VAL
1156			MMCR1_CK_VAL=$MMCR1_VAL
1157			MMCRA_CK_VAL=$MMCRA_VAL
1158		else
1159			# make sure all events are from the same group
1160			if test $MMCR0_CK_VAL != $MMCR0_VAL \
1161				-o $MMCR1_CK_VAL != $MMCR1_VAL \
1162				-o $MMCRA_CK_VAL != $MMCRA_VAL ; then
1163				echo "ERROR: The specified events are not from the same group."
1164				echo "       Use 'opcontrol --list-events' to see event groupings."
1165				exit 1
1166			fi
1167		fi
1168
1169		# Check if all user/kernel flags per-counter are matching.
1170		if [ "$USER_CK" = "" ] ; then
1171			USER_CK=$USER
1172			KERNEL_CK=$KERNEL
1173		else
1174			if test $USER_CK != $USER \
1175				-o $KERNEL_CK != $KERNEL ; then
1176				echo "ERROR: All kernel/user event flags must match."
1177				exit 1
1178			fi
1179		fi
1180	fi
1181	if [ "$CPUTYPE" = "ppc64/cell-be" ]; then
1182		event_num=`echo $EVENT_STR | awk '{print $1}'`
1183		# PPU event and cycle events can be measured at
1184		# the same time.  SPU event can not be measured
1185		# at the same time as any other event.  Similarly for
1186		# SPU Cycles
1187
1188		# We use EVNT_MSK to track what events have already
1189		# been seen.  Valid values are:
1190		#    NULL string -  no events seen yet
1191		#    1 - PPU CYCLES or PPU Event seen
1192		#    2 - SPU CYCLES seen
1193		#    3 - SPU EVENT seen
1194
1195		# check if event is PPU_CYCLES
1196		if [ "$event_num" = "1" ]; then
1197			if [ "$EVNT_MSK" = "1" ] || [ "$EVNT_MSK" = "" ]; then
1198				EVNT_MSK=1
1199			else
1200				echo "PPU CYCLES not compatible with previously specified event"
1201				exit 1
1202		fi
1203
1204		# check if event is SPU_CYCLES
1205		elif [ "$event_num" = "2" ]; then
1206			if [ "$EVNT_MSK" = "" ]; then
1207				EVNT_MSK=2
1208			else
1209				echo "SPU CYCLES not compatible with any other event"
1210				exit 1
1211			fi
1212
1213		# check if event is SPU Event profiling
1214		elif [ "$event_num" -ge "4100" ] && [ "$event_num" -le "4163" ] ; then
1215			if [ "$EVNT_MSK" = "" ]; then
1216				EVNT_MSK=3
1217			else
1218				echo "SPU event profiling not compatible with any other event"
1219				exit 1
1220			fi
1221
1222			# Check to see that the kernel supports SPU event
1223			# profiling.  Note, if the file exits it should have
1224			# the LSB bit set to 1 indicating SPU event profiling
1225			# support. For now, it is sufficient to test that the
1226			# file exists.
1227			if test ! -f /dev/oprofile/cell_support; then
1228				echo "Kernel does not support SPU event profiling"
1229				exit 1
1230			fi
1231
1232			# check if event is PPU Event profiling (all other
1233			# events are PPU events)
1234		else
1235			if [ "$EVNT_MSK" = "1" ] || [ "$EVNT_MSK" = "" ]; then
1236				EVNT_MSK=1
1237			else
1238				echo "PPU profiling not compatible with previously specified event"
1239				exit 1
1240			fi
1241		fi
1242	fi
1243	len=`echo -n $event_num | wc -m`
1244	num_chars_in_grpid=`expr $len - 2`
1245	GRP_NUM_VAL=`echo | awk '{print substr("'"${event_num}"'",1,"'"${num_chars_in_grpid}"'")}'`
1246	if [ "$GRP_NUM_CK_VAL" = "" ] ; then
1247		GRP_NUM_CK_VAL=$GRP_NUM_VAL
1248	else
1249		if test $GRP_NUM_CK_VAL != $GRP_NUM_VAL ; then
1250			echo "ERROR: The specified events are not from the same group." >&2
1251			echo "       Use 'opcontrol --list-events' to see event groupings." >&2
1252			exit 1
1253		fi
1254	fi
1255}
1256
1257
1258do_param_setup()
1259{
1260	# different names
1261	if test $BUF_SIZE != 0; then
1262		if test "$KERNEL_SUPPORT" = "yes"; then
1263			echo $BUF_SIZE >$MOUNT/buffer_size
1264		else
1265			$SYSCTL -w dev.oprofile.bufsize=$BUF_SIZE
1266		fi
1267	fi
1268
1269	if test $BUF_WATERSHED != 0; then
1270		if test "$KERNEL_SUPPORT" = "yes"; then
1271			echo $BUF_WATERSHED >$MOUNT/buffer_watershed
1272		else
1273			echo "buffer-watershed not supported - ignored" >&2
1274		fi
1275	fi
1276
1277	if test $CPU_BUF_SIZE != 0; then
1278		if test "$KERNEL_SUPPORT" = "yes"; then
1279			echo $CPU_BUF_SIZE >$MOUNT/cpu_buffer_size
1280		else
1281			echo "cpu-buffer-size not supported - ignored" >&2
1282		fi
1283	fi
1284
1285	if test -n "$ACTIVE_DOMAINS"; then
1286		if test "$KERNEL_SUPPORT" = "yes"; then
1287			echo $ACTIVE_DOMAINS >$MOUNT/active_domains
1288		else
1289			echo "active-domains not supported - ignored" >&2
1290		fi
1291	fi
1292
1293	if test $NOTE_SIZE != 0; then
1294		set_param notesize $NOTE_SIZE
1295	fi
1296
1297	if test "$KERNEL_SUPPORT" = "yes" -a -f $MOUNT/backtrace_depth; then
1298		set_param backtrace_depth $CALLGRAPH
1299	elif test "$CALLGRAPH" != "0"; then
1300		echo "Call-graph profiling not supported - ignored" >&2
1301	fi
1302
1303	if test "$IS_TIMER" = 1; then
1304		return
1305	fi
1306
1307	# use the default setup if none set
1308	if test "$NR_CHOSEN" = 0; then
1309		set_event 0 $DEFAULT_EVENT
1310		NR_CHOSEN=1
1311		HW_CTRS=`$OPHELP --check-events $DEFAULT_EVENT --callgraph=$CALLGRAPH`
1312		echo "Using default event: $DEFAULT_EVENT"
1313	fi
1314
1315	# Necessary in this case :
1316	# opcontrol ctr0-on ctr1-on then opcontrol ctr0-on
1317	for f in $OP_COUNTERS ; do
1318		set_ctr_param $f enabled 0
1319		set_ctr_param $f event 0
1320		set_ctr_param $f count 0
1321	done
1322
1323	# Check if driver has IBS support
1324	if test -d $MOUNT/ibs_fetch; then
1325		# Reset driver's IBS fetch setting
1326		set_param ibs_fetch/enable 0
1327	fi
1328	
1329	if test -d $MOUNT/ibs_op ; then
1330		# Reset driver's IBS op setting
1331		set_param ibs_op/enable 0
1332	fi	
1333
1334	verify_counters
1335
1336	OPROFILED_EVENTS=
1337	for f in `seq 0 $((NR_CHOSEN - 1))`; do
1338		get_event $f
1339		if test "$GOTEVENT" != ""; then
1340			EVENT=`echo $GOTEVENT | awk -F: '{print $1}'`
1341			EVENT_STR=`$OPHELP $EVENT`
1342			EVENT_VAL=`echo $EVENT_STR | awk '{print $1}'`
1343			COUNT=`echo $GOTEVENT | awk -F: '{print $2}'`
1344			UNIT_MASK=`echo $GOTEVENT | awk -F: '{print $3}'`
1345			KERNEL=`echo $GOTEVENT | awk -F: '{print $4}'`
1346			USER=`echo $GOTEVENT | awk -F: '{print $5}'`
1347			CTR=`echo $HW_CTRS | awk "{print \\$$((f + 1))}"`
1348			check_event_mapping_data
1349
1350			if test "$EVENT" = "SPU_CYCLES"; then
1351				if test "$SEPARATE_KERNEL" = "1"; then
1352					SEPARATE_KERNEL=0
1353					echo "Ignoring --separate=kernel option with SPU_CYCLES"
1354				fi
1355				if test "$SEPARATE_LIB" = "0"; then
1356					SEPARATE_LIB=1
1357					echo "Forcing required option --separate=lib with SPU_CYCLES"
1358				fi
1359
1360				# It is possible for a single application to be
1361				# running on all SPUs simultaneously.  Without
1362				# SEPARATE_CPU, the resulting sample data would
1363				# consist of a single sample file.  If all SPUs
1364				# were truly running the same code, the merging
1365				# of sample data would be fine.  However, an
1366				# application file may have multiple SPU images
1367				# embedded within it, resulting in different
1368				# code running on different SPUs.  Therefore,
1369				# we force SEPARATE_CPU in order to properly
1370				# handle this case.
1371				if test "$SEPARATE_CPU" = "0"; then
1372					SEPARATE_CPU=1
1373					echo "Forcing required option --separate=cpu with SPU_CYCLES"
1374
1375				fi
1376			fi
1377
1378			if [ "$CTR" = "ibs_fetch" -o "$CTR" = "ibs_op" ] ; then
1379				# Handle IBS events setup
1380				do_param_setup_ibs
1381				continue
1382			fi
1383
1384			if test "$EVENT" = "RTC_INTERRUPTS"; then
1385				set_param rtc_value $COUNT
1386				$SYSCTL -w dev.oprofile.rtc_value=$COUNT
1387			else
1388				set_ctr_param $CTR enabled 1
1389				set_ctr_param $CTR event $EVENT_VAL
1390				loop_count=1
1391				for i in ${EVENT_STR}; do
1392					#Skip first argument of EVENT_STR (event val) since we've already
1393					#processed that value.
1394					if test "$loop_count" -gt 1; then
1395						KEY=`echo $i | awk -F: '{print $1}'`
1396						VAL=`echo $i | awk -F: '{print $2}'`
1397						set_ctr_param "" $KEY $VAL
1398					fi
1399					loop_count=$((loop_count+1))
1400				done
1401				set_ctr_param $CTR count $COUNT
1402				set_ctr_param $CTR kernel $KERNEL
1403				set_ctr_param $CTR user $USER
1404				set_ctr_param $CTR unit_mask $UNIT_MASK
1405			fi
1406			OPROFILED_EVENTS=${OPROFILED_EVENTS}$EVENT:$EVENT_VAL:
1407			OPROFILED_EVENTS=${OPROFILED_EVENTS}$CTR:$COUNT:$UNIT_MASK:
1408			OPROFILED_EVENTS=${OPROFILED_EVENTS}$KERNEL:$USER,
1409		fi
1410	done
1411
1412	# For PPC64 architectures we need to set the enable_kernel and
1413	# enable_user flags for enabling/disabling user/kernel domain
1414	# profiling. All per-counter user/kernel flags must match.
1415	# This condition is checked previously by check_event_mapping_data.
1416	# This statement uses the last event's user/kernel flags to set
1417	# /dev/oprofile/enable_kernel and /dev/oprofile/enable_user.
1418	is_non_cell_ppc64_variant $CPUTYPE
1419	if test $? -ne 0 ; then
1420		set_param "enable_kernel" $KERNEL
1421		set_param "enable_user" $USER
1422	fi
1423
1424}
1425
1426
1427do_start_daemon()
1428{
1429
1430	if test -f "$LOCK_FILE"; then
1431		kill -0 `cat $LOCK_FILE` 2>/dev/null
1432		if test "$?" -eq 0; then
1433			return;
1434		else
1435			echo "Detected stale lock file. Removing." >&2
1436			rm -f "$LOCK_FILE"
1437		fi
1438	fi
1439
1440	do_setup
1441	check_valid_args
1442	get_image_range "linux"
1443	get_image_range "xen"
1444	do_param_setup
1445
1446	OPD_ARGS=" \
1447		--session-dir=$SESSION_DIR \
1448		--separate-lib=$SEPARATE_LIB \
1449		--separate-kernel=$SEPARATE_KERNEL \
1450		--separate-thread=$SEPARATE_THREAD \
1451		--separate-cpu=$SEPARATE_CPU"
1452
1453	if test "$IS_TIMER" = 1; then
1454		OPD_ARGS="$OPD_ARGS --events="
1455	else
1456		if ! test -z "$OPROFILED_EVENTS"; then
1457			OPD_ARGS="$OPD_ARGS --events=$OPROFILED_EVENTS"
1458		fi
1459	fi
1460
1461	if test "$VMLINUX" = "none"; then
1462		OPD_ARGS="$OPD_ARGS --no-vmlinux"
1463	else
1464		OPD_ARGS="$OPD_ARGS --vmlinux=$VMLINUX --kernel-range=$KERNEL_RANGE"
1465	fi
1466
1467	if ! test "$XENIMAGE" = "none"; then
1468		OPD_ARGS="$OPD_ARGS --xen-image=$XENIMAGE --xen-range=$XEN_RANGE"
1469	fi
1470
1471	if ! test -z "$IMAGE_FILTER"; then
1472		OPD_ARGS="$OPD_ARGS --image=$IMAGE_FILTER"
1473	fi
1474
1475	if test -n "$VERBOSE"; then
1476		OPD_ARGS="$OPD_ARGS --verbose=$VERBOSE"
1477	fi
1478
1479	help_start_daemon_with_ibs
1480
1481	vecho "executing oprofiled $OPD_ARGS"
1482
1483	$OPROFILED $OPD_ARGS
1484
1485	COUNT=0
1486	while ! test -f "$SESSION_DIR/lock"
1487	do
1488		sleep 1
1489		COUNT=`expr $COUNT + 1`
1490		if test "$COUNT" -eq 10; then
1491			echo "Couldn't start oprofiled." >&2
1492			echo "Check the log file \"$LOG_FILE\" and kernel syslog" >&2
1493			exit 1
1494		fi
1495	done
1496
1497	echo "Daemon started."
1498}
1499
1500do_start()
1501{
1502	prep_jitdump;
1503	if test "$KERNEL_SUPPORT" = "yes"; then
1504		echo 1 >$MOUNT/enable
1505	fi
1506	kill -USR1 `cat $LOCK_FILE` 2>/dev/null
1507	echo "Profiler running."
1508}
1509
1510
1511# print status
1512do_status()
1513{
1514	OPROFILED_PID=`cat $SESSION_DIR/lock 2>/dev/null`
1515	if test -n "$OPROFILED_PID" -a -d "/proc/$OPROFILED_PID"; then
1516		echo "Daemon running: pid $OPROFILED_PID"
1517	else
1518		echo "Daemon not running"
1519	fi
1520
1521	if test "$NR_CHOSEN" != "0"; then
1522		for f in `seq 0 $((NR_CHOSEN - 1))`; do
1523			get_event $f
1524			echo "Event $f: $GOTEVENT"
1525		done
1526	fi
1527
1528	SEPARATE=""
1529	if test "$SEPARATE_LIB" = "1"; then
1530		SEPARATE="library";
1531	fi
1532	if test "$SEPARATE_KERNEL" = "1"; then
1533		SEPARATE="$SEPARATE kernel";
1534	fi
1535	if test "$SEPARATE_THREAD" = "1"; then
1536		SEPARATE="$SEPARATE thread";
1537	fi
1538	if test "$SEPARATE_CPU" = "1"; then
1539		SEPARATE="$SEPARATE cpu";
1540	fi
1541
1542	if test -z "$SEPARATE"; then
1543		SEPARATE=none
1544	fi
1545
1546	echo "Separate options: $SEPARATE"
1547	echo "vmlinux file: $VMLINUX"
1548
1549	if test -z "$IMAGE_FILTER"; then
1550		echo "Image filter: none"
1551	else
1552		echo "Image filter: $IMAGE_FILTER"
1553	fi
1554
1555	echo "Call-graph depth: $CALLGRAPH"
1556	if test "$BUF_SIZE" != "0"; then
1557		echo "Buffer size: $BUF_SIZE"
1558	fi
1559	if test "$KERNEL_SUPPORT" != "yes"; then
1560		if test "$NOTE_SIZE" != "0"; then
1561			echo "Note buffer size: $NOTE_SIZE"
1562		fi
1563	else
1564		if test "$BUF_WATERSHED" != "0"; then
1565			echo "CPU buffer watershed: $BUF_WATERSHED"
1566		fi
1567		if test "$CPU_BUF_SIZE" != "0"; then
1568			echo "CPU buffer size: $CPU_BUF_SIZE"
1569		fi
1570	fi
1571
1572	exit 0
1573}
1574
1575
1576# do_dump_data
1577# returns 0 if successful
1578# returns 1 if the daemon is unable to dump data
1579# exit 1 if we need to be root to dump
1580do_dump_data()
1581{
1582	# make sure that the daemon is not dead and gone
1583	if test -e "$SESSION_DIR/lock"; then
1584		OPROFILED_PID=`cat $SESSION_DIR/lock`
1585		if test ! -d "/proc/$OPROFILED_PID"; then
1586			echo "dump fail: daemon died during last run ?" >&2
1587			return 1;
1588		fi
1589	else
1590		return 1;
1591	fi
1592
1593	if test "$KERNEL_SUPPORT" = "yes"; then
1594		if ! test -w $MOUNT/dump; then
1595			if test `id -u` != "0"; then
1596				echo "You must be root to dump with this kernel version"
1597				exit 1
1598			fi
1599		fi
1600		# trigger oprofiled to execute opjitconv
1601		echo do_jitconv > $SESSION_DIR/opd_pipe
1602		rm -f "$SESSION_DIR/complete_dump"
1603		echo 1 > $MOUNT/dump
1604		# loop until the complete_dump file is created to
1605		# signal that the dump has been completed
1606		while [ \( ! -e "$SESSION_DIR/complete_dump" \) ]
1607		do
1608			if test ! -d "/proc/$OPROFILED_PID"; then
1609				echo "dump fail: either daemon died during last run or dies during dump" >&2
1610				return 1
1611			fi
1612			sleep 1;
1613		done
1614	else
1615		echo 1 > $MOUNT/dump
1616		# HACK !
1617		sleep 2
1618	fi
1619	return 0;
1620}
1621
1622
1623# do_dump
1624# returns 0 if successful
1625# exits if unsuccessful
1626do_dump()
1627{
1628	do_dump_data
1629	if test $? -ne 0 -a "$ONLY_DUMP" = "yes"; then
1630		echo "Unable to complete dump of oprofile data: is the oprofile daemon running?" >& 2
1631		exit 1;
1632	fi
1633	return 0;
1634}
1635
1636# tell daemon to re-open the sample files
1637hup_daemon()
1638{
1639	if test -f "$LOCK_FILE"; then
1640		echo -n "Signalling daemon... "
1641		kill -HUP `cat $LOCK_FILE`
1642		echo "done"
1643	fi
1644}
1645
1646
1647# move all the sample files to a sample directory
1648do_save_session()
1649{
1650	SAVE_DIR="${SAMPLES_DIR}/${SAVE_NAME}"
1651
1652	if test -e "$SAVE_DIR"; then
1653		echo "session $SAVE_DIR already exists" >&2
1654		exit 1
1655	fi
1656
1657	if ! test -e $CURRENT_SAMPLES_DIR; then
1658		echo "$CURRENT_SAMPLES_DIR doesn't exist: nothing to save" >&2
1659		exit 0
1660	fi
1661
1662	# FIXME: I don't think it's worth checking for empty current directory
1663
1664	mv $CURRENT_SAMPLES_DIR $SAVE_DIR
1665	if test "$?" != "0"; then
1666		echo "Couldn't move $CURRENT_SAMPLES_DIR to $SAVE_DIR" >&2
1667		exit 1
1668	fi
1669
1670	hup_daemon
1671}
1672
1673
1674# remove all the sample files
1675do_reset()
1676{
1677	if test -z "$SAMPLES_DIR"; then
1678		echo "opcontrol:do_reset() SAMPLES_DIR is empty!"
1679		exit 1;
1680	fi
1681
1682	# daemon use {kern} and {root} subdir, it's not a typo to not use ${}
1683	move_and_remove $SAMPLES_DIR/current/{kern}
1684	move_and_remove $SAMPLES_DIR/current/{root}
1685	move_and_remove $SAMPLES_DIR/current/stats
1686
1687	# clear temp directory for jitted code
1688	prep_jitdump;
1689
1690	hup_daemon
1691}
1692
1693
1694do_deinit()
1695{
1696	# unmount /dev/oprofile if it is mounted
1697	OPROF_FS=`grep /dev/oprofile /etc/mtab`
1698	if test -n "$OPROF_FS"; then
1699		umount /dev/oprofile
1700	fi
1701	# unload the oprofile module if it is around
1702	OPROF_MOD=`lsmod | grep oprofile`
1703	if test -n "$OPROF_MOD"; then
1704		echo "Unloading oprofile module" >& 2
1705		rmmod oprofile
1706	fi
1707}
1708
1709
1710# The function that calls the appropriate operations
1711do_operations()
1712{
1713	# INIT always done by load_module to get access to cputype
1714	# thus INIT is a noop
1715
1716	if test "$STATUS" = "yes"; then
1717		do_status
1718	fi
1719
1720	if test "$SETUP" = "yes"; then
1721		check_valid_args
1722		do_save_setup
1723	fi
1724
1725	if test "$START_DAEMON" = "yes"; then
1726		do_start_daemon
1727	fi
1728
1729	if test "$START" = "yes"; then
1730		do_start_daemon
1731		do_start
1732	fi
1733
1734	if test "$DUMP" = "yes"; then
1735		do_dump
1736	fi
1737
1738	if test "$SAVE_SESSION" = "yes"; then
1739		do_save_session
1740	fi
1741
1742	if test "$STOP" = "yes"; then
1743		do_stop
1744	fi
1745
1746	if test "$KILL_DAEMON" = "yes"; then
1747		do_kill_daemon
1748	fi
1749
1750	if test "$RESET" = "yes"; then
1751		do_reset
1752	fi
1753
1754	if test "$DEINIT" = "yes"; then
1755		do_deinit
1756	fi
1757}
1758
1759# early check for --version, --help and --session-dir
1760check_options_early()
1761{
1762
1763	OPHELP="$OPDIR/ophelp"
1764
1765	for i in $@; do
1766		# added to handle arg=val parameters
1767		arg=`printf %s $i | awk -F= '{print $1}'`
1768		val=`printf %s $i | awk -F= '{print $2}'`
1769		case "$arg" in
1770			-\?|--help)
1771				do_help
1772				exit 0
1773				;;
1774
1775			-v|--version)
1776				echo -n "`basename $0`: "
1777				$OPHELP --version | cut -d' ' -f2-
1778				exit 0
1779				;;
1780			--session-dir)
1781				error_if_empty $arg $val
1782				SESSION_DIR="$val"
1783				DO_SETUP=yes
1784				# do not exit early
1785				;;
1786
1787		esac
1788	done
1789}
1790
1791
1792# determine which module is loaded
1793check_version()
1794{
1795	OPROFILE_AVAILABLE=no
1796	grep oprofilefs /etc/mtab >/dev/null
1797	if test "$?" -eq 0; then
1798		# need to have oprofilefs mounted for this to work on 2.6
1799		KERNEL_SUPPORT=yes
1800		OPROFILE_AVAILABLE=yes
1801		return
1802	fi
1803	# need to have /proc/oprof available for this to work on 2.4
1804	grep oprof /proc/devices >/dev/null
1805	if test "$?" -eq 0; then
1806		KERNEL_SUPPORT=no
1807		OPROFILE_AVAILABLE=yes
1808		return
1809	fi
1810}
1811
1812# error out if the module is not loaded
1813check_oprofile_available()
1814{
1815	if test "$OPROFILE_AVAILABLE" != "yes"; then
1816		echo "Kernel support not available, missing opcontrol --init as root ?"
1817		exit 1
1818	fi
1819}
1820
1821
1822try_reset_sample_file()
1823{
1824	# special case to avoid loading the module, it works only if the
1825	# daemon is not running because --reset imply --dump. Rather to check
1826	# if the daemon is running we check if the module is loaded because
1827	# we are only trying to avoid its load, if the check fails we fallback
1828	# to the normal dump / reset sequence.
1829	if test -z "$2" -a "$1" = "--reset"; then
1830		check_version
1831		if test "$OPROFILE_AVAILABLE" != "yes"; then
1832			do_init_daemon_vars
1833			do_reset
1834			exit 0
1835		fi
1836	fi
1837}
1838
1839#
1840# Begin IBS Specific Functions
1841#
1842verify_ibs()
1843{
1844	IBS_EVENT=`echo $1| awk -F: '{print $1}'`
1845	IBS_COUNT=`echo $1 | awk -F: '{print $2}'`
1846	IBS_MASK=`echo $1 | awk -F: '{print $3}'`
1847	
1848	IBS_TYPE=`$OPHELP --check-events $1`
1849	if test "$?" != "0" ; then
1850		exit 1
1851	fi
1852			
1853	if [ "$IBS_TYPE" = "ibs_fetch " ] ; then
1854		# Check IBS_COUNT consistency
1855		if test "$IBS_FETCH_COUNT" = "0" ; then 
1856			IBS_FETCH_COUNT=$IBS_COUNT
1857			IBS_FETCH_MASK=$IBS_MASK
1858		elif test "$IBS_FETCH_COUNT" != "$IBS_COUNT" ; then
1859			echo "All IBS Fetch must have the same count."
1860			exit 1
1861		fi
1862
1863		# Check IBS_MASK consistency
1864		if test "$IBS_FETCH_MASK" != "$IBS_MASK" ; then
1865			echo "All IBS Fetch must have the same unitmask."
1866			exit 1
1867		fi
1868
1869	elif [ "$IBS_TYPE" = "ibs_op " ] ; then
1870		# Check IBS_COUNT consistency
1871		if test "$IBS_OP_COUNT" = "0" ; then 
1872			IBS_OP_COUNT=$IBS_COUNT
1873			IBS_OP_MASK=$IBS_MASK
1874		elif test "$IBS_OP_COUNT" != "$IBS_COUNT" ; then
1875			echo "All IBS Op must have the same count."
1876			exit 1
1877		fi
1878
1879		# Check IBS_MASK consistency
1880		if test "$IBS_OP_MASK" != "$IBS_MASK" ; then
1881			echo "All IBS Op must have the same unitmask."
1882			exit 1
1883		fi
1884	fi
1885
1886	return
1887}
1888
1889
1890do_param_setup_ibs()
1891{
1892	if test "$KERNEL_SUPPORT" != "yes" ; then
1893		echo "ERROR: No kernel support for IBS profiling."
1894		exit 1	
1895	fi
1896
1897	# Check if driver has IBS support
1898	if test ! -d $MOUNT/ibs_fetch -o ! -d $MOUNT/ibs_op ; then
1899		echo "ERROR: No kernel support for IBS profiling."
1900		exit 1	
1901	fi	
1902
1903	if test `echo $EVENT |  \
1904	awk '{ print substr($0, 1, 10)}'` = "IBS_FETCH_" ; then
1905		if test "$COUNT" != "0"; then
1906			if [ "$IBS_FETCH_EVENTS" = "" ] ; then
1907				IBS_FETCH_EVENTS="$EVENT"
1908			else
1909				IBS_FETCH_EVENTS="$IBS_FETCH_EVENTS,$EVENT"
1910			fi
1911			IBS_FETCH_COUNT=$COUNT
1912			set_param ibs_fetch/max_count $COUNT
1913			set_param ibs_fetch/rand_enable 1
1914			set_param ibs_fetch/enable 1
1915		else
1916			set_param ibs_fetch/enable 0
1917		fi
1918
1919	elif test `echo $EVENT |  \
1920	awk '{ print substr($0, 1, 7)}'` = "IBS_OP_" ; then
1921		if test "$COUNT" != "0"; then
1922			if [ "$IBS_OP_EVENTS" = "" ] ; then
1923				IBS_OP_EVENTS="$EVENT"
1924			else
1925				IBS_OP_EVENTS="$IBS_OP_EVENTS,$EVENT"
1926			fi
1927			IBS_OP_COUNT=$COUNT
1928			IBS_OP_UNITMASK=$UNIT_MASK
1929
1930			set_param ibs_op/max_count $COUNT
1931			set_param ibs_op/enable 1
1932
1933			# NOTE: We default to use dispatched_op if available. 
1934			#       Some of the older family10 system does not have
1935			#       dispatched_ops feature.
1936			#	dispatched op is enabled by bit 1 of the unitmask
1937			if test -f $MOUNT/ibs_op/dispatched_ops ; then
1938				IBS_OP_DISPATCHED_OP=$(( IBS_OP_UNITMASK & 0x1 ))
1939				set_param ibs_op/dispatched_ops $IBS_OP_DISPATCHED_OP
1940			fi
1941		else
1942			set_param ibs_op/enable 0
1943		fi
1944	fi
1945}
1946
1947
1948help_start_daemon_with_ibs()
1949{
1950	if test "$IBS_FETCH_COUNT" != "0" -o "$IBS_OP_COUNT" != "0" ; then
1951		OPD_ARGS="${OPD_ARGS} --ext-feature=ibs:"
1952		if test "$IBS_FETCH_COUNT" != "0"; then
1953			OPD_ARGS="${OPD_ARGS}fetch:$IBS_FETCH_EVENTS:$IBS_FETCH_COUNT:$IBS_FETCH_UNITMASK|"
1954		fi
1955
1956		if test "$IBS_OP_COUNT" != "0"; then
1957			OPD_ARGS="${OPD_ARGS}op:$IBS_OP_EVENTS:$IBS_OP_COUNT:$IBS_OP_UNITMASK"
1958		fi
1959	fi
1960}
1961
1962#
1963# End IBS Specific Functions
1964#
1965
1966# main
1967
1968# determine the location of opcontrol and related programs
1969if test -z "$OPDIR"; then
1970	BINDIR="/usr/bin"
1971	OPCONTROL=`$BINDIR/which $0`
1972	OPDIR=`$BINDIR/dirname $OPCONTROL`
1973fi
1974
1975PATH=$OPDIR:/usr/local/bin:/usr/local/sbin:/bin:/sbin:/usr/bin:/usr/sbin
1976
1977check_options_early $@
1978
1979if test -z "$1"; then
1980	do_help
1981	exit 0
1982fi
1983
1984if test `id -u` = "0"; then
1985	try_reset_sample_file $@
1986
1987	load_module
1988fi
1989check_version
1990
1991# Except --reset, even the few operations allowed as non root needs the
1992# kernel support, if we don't error out now the error message will be obscure
1993check_oprofile_available
1994
1995do_init
1996if test `id -u` != "0"; then
1997    if test -z "$2"; then
1998	case "$1" in
1999	    --dump|-d)
2000		ONLY_DUMP=yes
2001		do_dump
2002		exit 0;
2003		;;
2004	    --list-events|-l)
2005		exec $OPHELP
2006		exit 0;
2007		;;
2008	    *)
2009		echo "Normal users are limited to either '--dump' or '--list-events'." >&2
2010		exit 1
2011		;;
2012	esac
2013    else
2014	echo "Normal users are limited to either '--dump' or '--list-events'." >&2
2015	exit 1
2016    fi
2017fi
2018
2019do_options $@
2020do_operations
2021