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