162306a36Sopenharmony_ci#!/bin/sh
262306a36Sopenharmony_ci# SPDX-License-Identifier: GPL-2.0-only
362306a36Sopenharmony_ci
462306a36Sopenharmony_ciusage() {
562306a36Sopenharmony_ci	echo "Ftrace boottime trace test tool"
662306a36Sopenharmony_ci	echo "Usage: $0 [--apply|--init] [--debug] BOOTCONFIG-FILE"
762306a36Sopenharmony_ci	echo "    --apply: Test actual apply to tracefs (need sudo)"
862306a36Sopenharmony_ci	echo "    --init:  Initialize ftrace before applying (imply --apply)"
962306a36Sopenharmony_ci	exit 1
1062306a36Sopenharmony_ci}
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_ci[ $# -eq 0 ] && usage
1362306a36Sopenharmony_ci
1462306a36Sopenharmony_ciBCONF=
1562306a36Sopenharmony_ciDEBUG=
1662306a36Sopenharmony_ciAPPLY=
1762306a36Sopenharmony_ciINIT=
1862306a36Sopenharmony_ciwhile [ x"$1" != x ]; do
1962306a36Sopenharmony_ci	case "$1" in
2062306a36Sopenharmony_ci	"--debug")
2162306a36Sopenharmony_ci		DEBUG=$1;;
2262306a36Sopenharmony_ci	"--apply")
2362306a36Sopenharmony_ci		APPLY=$1;;
2462306a36Sopenharmony_ci	"--init")
2562306a36Sopenharmony_ci		APPLY=$1
2662306a36Sopenharmony_ci		INIT=$1;;
2762306a36Sopenharmony_ci	*)
2862306a36Sopenharmony_ci		[ ! -f $1 ] && usage
2962306a36Sopenharmony_ci		BCONF=$1;;
3062306a36Sopenharmony_ci	esac
3162306a36Sopenharmony_ci	shift 1
3262306a36Sopenharmony_cidone
3362306a36Sopenharmony_ci
3462306a36Sopenharmony_ciif [ x"$APPLY" != x ]; then
3562306a36Sopenharmony_ci	if [ `id -u` -ne 0 ]; then
3662306a36Sopenharmony_ci		echo "This must be run by root user. Try sudo." 1>&2
3762306a36Sopenharmony_ci		exec sudo $0 $DEBUG $APPLY $BCONF
3862306a36Sopenharmony_ci	fi
3962306a36Sopenharmony_cifi
4062306a36Sopenharmony_ci
4162306a36Sopenharmony_cirun_cmd() { # command
4262306a36Sopenharmony_ci	echo "$*"
4362306a36Sopenharmony_ci	if [ x"$APPLY" != x ]; then # apply command
4462306a36Sopenharmony_ci		eval $*
4562306a36Sopenharmony_ci	fi
4662306a36Sopenharmony_ci}
4762306a36Sopenharmony_ci
4862306a36Sopenharmony_ciif [ x"$DEBUG" != x ]; then
4962306a36Sopenharmony_ci	set -x
5062306a36Sopenharmony_cifi
5162306a36Sopenharmony_ci
5262306a36Sopenharmony_ciTRACEFS=`grep -m 1 -w tracefs /proc/mounts | cut -f 2 -d " "`
5362306a36Sopenharmony_ciif [ -z "$TRACEFS" ]; then
5462306a36Sopenharmony_ci	if ! grep -wq debugfs /proc/mounts; then
5562306a36Sopenharmony_ci		echo "Error: No tracefs/debugfs was mounted." 1>&2
5662306a36Sopenharmony_ci		exit 1
5762306a36Sopenharmony_ci	fi
5862306a36Sopenharmony_ci	TRACEFS=`grep -m 1 -w debugfs /proc/mounts | cut -f 2 -d " "`/tracing
5962306a36Sopenharmony_ci	if [ ! -d $TRACEFS ]; then
6062306a36Sopenharmony_ci		echo "Error: ftrace is not enabled on this kernel." 1>&2
6162306a36Sopenharmony_ci		exit 1
6262306a36Sopenharmony_ci	fi
6362306a36Sopenharmony_cifi
6462306a36Sopenharmony_ci
6562306a36Sopenharmony_ciif [ x"$INIT" != x ]; then
6662306a36Sopenharmony_ci	. `dirname $0`/ftrace.sh
6762306a36Sopenharmony_ci	(cd $TRACEFS; initialize_ftrace)
6862306a36Sopenharmony_cifi
6962306a36Sopenharmony_ci
7062306a36Sopenharmony_ci. `dirname $0`/xbc.sh
7162306a36Sopenharmony_ci
7262306a36Sopenharmony_ci######## main #########
7362306a36Sopenharmony_ciset -e
7462306a36Sopenharmony_ci
7562306a36Sopenharmony_cixbc_init $BCONF
7662306a36Sopenharmony_ci
7762306a36Sopenharmony_ciset_value_of() { # key file
7862306a36Sopenharmony_ci	if xbc_has_key $1; then
7962306a36Sopenharmony_ci		val=`xbc_get_val $1 1`
8062306a36Sopenharmony_ci		run_cmd "echo '$val' >> $2"
8162306a36Sopenharmony_ci	fi
8262306a36Sopenharmony_ci}
8362306a36Sopenharmony_ci
8462306a36Sopenharmony_ciset_array_of() { # key file
8562306a36Sopenharmony_ci	if xbc_has_key $1; then
8662306a36Sopenharmony_ci		xbc_get_val $1 | while read line; do
8762306a36Sopenharmony_ci			run_cmd "echo '$line' >> $2"
8862306a36Sopenharmony_ci		done
8962306a36Sopenharmony_ci	fi
9062306a36Sopenharmony_ci}
9162306a36Sopenharmony_ci
9262306a36Sopenharmony_cicompose_synth() { # event_name branch
9362306a36Sopenharmony_ci	echo -n "$1 "
9462306a36Sopenharmony_ci	xbc_get_val $2 | while read field; do echo -n "$field; "; done
9562306a36Sopenharmony_ci}
9662306a36Sopenharmony_ci
9762306a36Sopenharmony_ciprint_hist_array() { # prefix key
9862306a36Sopenharmony_ci	__sep="="
9962306a36Sopenharmony_ci	if xbc_has_key ${1}.${2}; then
10062306a36Sopenharmony_ci		echo -n ":$2"
10162306a36Sopenharmony_ci		xbc_get_val ${1}.${2} | while read field; do
10262306a36Sopenharmony_ci			echo -n "$__sep$field"; __sep=","
10362306a36Sopenharmony_ci		done
10462306a36Sopenharmony_ci	fi
10562306a36Sopenharmony_ci}
10662306a36Sopenharmony_ci
10762306a36Sopenharmony_ciprint_hist_action_array() { # prefix key
10862306a36Sopenharmony_ci	__sep="("
10962306a36Sopenharmony_ci	echo -n ".$2"
11062306a36Sopenharmony_ci	xbc_get_val ${1}.${2} | while read field; do
11162306a36Sopenharmony_ci		echo -n "$__sep$field"; __sep=","
11262306a36Sopenharmony_ci	done
11362306a36Sopenharmony_ci	echo -n ")"
11462306a36Sopenharmony_ci}
11562306a36Sopenharmony_ci
11662306a36Sopenharmony_ciprint_hist_one_action() { # prefix handler param
11762306a36Sopenharmony_ci	echo -n ":${2}("`xbc_get_val ${1}.${3}`")"
11862306a36Sopenharmony_ci	if xbc_has_key "${1}.trace"; then
11962306a36Sopenharmony_ci		print_hist_action_array ${1} "trace"
12062306a36Sopenharmony_ci	elif xbc_has_key "${1}.save"; then
12162306a36Sopenharmony_ci		print_hist_action_array ${1} "save"
12262306a36Sopenharmony_ci	elif xbc_has_key "${1}.snapshot"; then
12362306a36Sopenharmony_ci		echo -n ".snapshot()"
12462306a36Sopenharmony_ci	fi
12562306a36Sopenharmony_ci}
12662306a36Sopenharmony_ci
12762306a36Sopenharmony_ciprint_hist_actions() { # prefix handler param
12862306a36Sopenharmony_ci	for __hdr in `xbc_subkeys ${1}.${2} 1 ".[0-9]"`; do
12962306a36Sopenharmony_ci		print_hist_one_action ${1}.${2}.$__hdr ${2} ${3}
13062306a36Sopenharmony_ci	done
13162306a36Sopenharmony_ci	if xbc_has_key ${1}.${2}.${3} ; then
13262306a36Sopenharmony_ci		print_hist_one_action ${1}.${2} ${2} ${3}
13362306a36Sopenharmony_ci	fi
13462306a36Sopenharmony_ci}
13562306a36Sopenharmony_ci
13662306a36Sopenharmony_ciprint_hist_var() { # prefix varname
13762306a36Sopenharmony_ci	echo -n ":${2}="`xbc_get_val ${1}.var.${2} | tr -d [:space:]`
13862306a36Sopenharmony_ci}
13962306a36Sopenharmony_ci
14062306a36Sopenharmony_ciprint_one_histogram() { # prefix
14162306a36Sopenharmony_ci	echo -n "hist"
14262306a36Sopenharmony_ci	print_hist_array $1 "keys"
14362306a36Sopenharmony_ci	print_hist_array $1 "values"
14462306a36Sopenharmony_ci	print_hist_array $1 "sort"
14562306a36Sopenharmony_ci	if xbc_has_key "${1}.size"; then
14662306a36Sopenharmony_ci		echo -n ":size="`xbc_get_val ${1}.size`
14762306a36Sopenharmony_ci	fi
14862306a36Sopenharmony_ci	if xbc_has_key "${1}.name"; then
14962306a36Sopenharmony_ci		echo -n ":name="`xbc_get_val ${1}.name`
15062306a36Sopenharmony_ci	fi
15162306a36Sopenharmony_ci	for __var in `xbc_subkeys "${1}.var" 1`; do
15262306a36Sopenharmony_ci		print_hist_var ${1} ${__var}
15362306a36Sopenharmony_ci	done
15462306a36Sopenharmony_ci	if xbc_has_key "${1}.pause"; then
15562306a36Sopenharmony_ci		echo -n ":pause"
15662306a36Sopenharmony_ci	elif xbc_has_key "${1}.continue"; then
15762306a36Sopenharmony_ci		echo -n ":continue"
15862306a36Sopenharmony_ci	elif xbc_has_key "${1}.clear"; then
15962306a36Sopenharmony_ci		echo -n ":clear"
16062306a36Sopenharmony_ci	fi
16162306a36Sopenharmony_ci	print_hist_actions ${1} "onmax" "var"
16262306a36Sopenharmony_ci	print_hist_actions ${1} "onchange" "var"
16362306a36Sopenharmony_ci	print_hist_actions ${1} "onmatch" "event"
16462306a36Sopenharmony_ci
16562306a36Sopenharmony_ci	if xbc_has_key "${1}.filter"; then
16662306a36Sopenharmony_ci		echo -n " if "`xbc_get_val ${1}.filter`
16762306a36Sopenharmony_ci	fi
16862306a36Sopenharmony_ci}
16962306a36Sopenharmony_ci
17062306a36Sopenharmony_cisetup_one_histogram() { # prefix trigger-file
17162306a36Sopenharmony_ci	run_cmd "echo '`print_one_histogram ${1}`' >> ${2}"
17262306a36Sopenharmony_ci}
17362306a36Sopenharmony_ci
17462306a36Sopenharmony_cisetup_histograms() { # prefix trigger-file
17562306a36Sopenharmony_ci	for __hist in `xbc_subkeys ${1} 1 ".[0-9]"`; do
17662306a36Sopenharmony_ci		setup_one_histogram ${1}.$__hist ${2}
17762306a36Sopenharmony_ci	done
17862306a36Sopenharmony_ci	if xbc_has_key ${1}.keys; then
17962306a36Sopenharmony_ci		setup_one_histogram ${1} ${2}
18062306a36Sopenharmony_ci	fi
18162306a36Sopenharmony_ci}
18262306a36Sopenharmony_ci
18362306a36Sopenharmony_cisetup_event() { # prefix group event [instance]
18462306a36Sopenharmony_ci	branch=$1.$2.$3
18562306a36Sopenharmony_ci	if [ "$4" ]; then
18662306a36Sopenharmony_ci		eventdir="$TRACEFS/instances/$4/events/$2/$3"
18762306a36Sopenharmony_ci	else
18862306a36Sopenharmony_ci		eventdir="$TRACEFS/events/$2/$3"
18962306a36Sopenharmony_ci	fi
19062306a36Sopenharmony_ci	# group enable
19162306a36Sopenharmony_ci	if [ "$3" = "enable" ]; then
19262306a36Sopenharmony_ci		run_cmd "echo 1 > ${eventdir}"
19362306a36Sopenharmony_ci		return
19462306a36Sopenharmony_ci	fi
19562306a36Sopenharmony_ci
19662306a36Sopenharmony_ci	case $2 in
19762306a36Sopenharmony_ci	kprobes)
19862306a36Sopenharmony_ci		xbc_get_val ${branch}.probes | while read line; do
19962306a36Sopenharmony_ci			run_cmd "echo 'p:kprobes/$3 $line' >> $TRACEFS/kprobe_events"
20062306a36Sopenharmony_ci		done
20162306a36Sopenharmony_ci		;;
20262306a36Sopenharmony_ci	synthetic)
20362306a36Sopenharmony_ci		run_cmd "echo '`compose_synth $3 ${branch}.fields`' >> $TRACEFS/synthetic_events"
20462306a36Sopenharmony_ci		;;
20562306a36Sopenharmony_ci	esac
20662306a36Sopenharmony_ci
20762306a36Sopenharmony_ci	set_value_of ${branch}.filter ${eventdir}/filter
20862306a36Sopenharmony_ci	set_array_of ${branch}.actions ${eventdir}/trigger
20962306a36Sopenharmony_ci
21062306a36Sopenharmony_ci	setup_histograms ${branch}.hist ${eventdir}/trigger
21162306a36Sopenharmony_ci
21262306a36Sopenharmony_ci	if xbc_has_key ${branch}.enable; then
21362306a36Sopenharmony_ci		run_cmd "echo 1 > ${eventdir}/enable"
21462306a36Sopenharmony_ci	fi
21562306a36Sopenharmony_ci}
21662306a36Sopenharmony_ci
21762306a36Sopenharmony_cisetup_events() { # prefix("ftrace" or "ftrace.instance.INSTANCE") [instance]
21862306a36Sopenharmony_ci	prefix="${1}.event"
21962306a36Sopenharmony_ci	if xbc_has_branch ${1}.event; then
22062306a36Sopenharmony_ci		for grpev in `xbc_subkeys ${1}.event 2`; do
22162306a36Sopenharmony_ci			setup_event $prefix ${grpev%.*} ${grpev#*.} $2
22262306a36Sopenharmony_ci		done
22362306a36Sopenharmony_ci	fi
22462306a36Sopenharmony_ci	if xbc_has_branch ${1}.event.enable; then
22562306a36Sopenharmony_ci		if [ "$2" ]; then
22662306a36Sopenharmony_ci			run_cmd "echo 1 > $TRACEFS/instances/$2/events/enable"
22762306a36Sopenharmony_ci		else
22862306a36Sopenharmony_ci			run_cmd "echo 1 > $TRACEFS/events/enable"
22962306a36Sopenharmony_ci		fi
23062306a36Sopenharmony_ci	fi
23162306a36Sopenharmony_ci}
23262306a36Sopenharmony_ci
23362306a36Sopenharmony_cisize2kb() { # size[KB|MB]
23462306a36Sopenharmony_ci	case $1 in
23562306a36Sopenharmony_ci	*KB)
23662306a36Sopenharmony_ci		echo ${1%KB};;
23762306a36Sopenharmony_ci	*MB)
23862306a36Sopenharmony_ci		expr ${1%MB} \* 1024;;
23962306a36Sopenharmony_ci	*)
24062306a36Sopenharmony_ci		expr $1 / 1024 ;;
24162306a36Sopenharmony_ci	esac
24262306a36Sopenharmony_ci}
24362306a36Sopenharmony_ci
24462306a36Sopenharmony_cisetup_instance() { # [instance]
24562306a36Sopenharmony_ci	if [ "$1" ]; then
24662306a36Sopenharmony_ci		instance="ftrace.instance.${1}"
24762306a36Sopenharmony_ci		instancedir=$TRACEFS/instances/$1
24862306a36Sopenharmony_ci	else
24962306a36Sopenharmony_ci		instance="ftrace"
25062306a36Sopenharmony_ci		instancedir=$TRACEFS
25162306a36Sopenharmony_ci	fi
25262306a36Sopenharmony_ci
25362306a36Sopenharmony_ci	set_array_of ${instance}.options ${instancedir}/trace_options
25462306a36Sopenharmony_ci	set_value_of ${instance}.trace_clock ${instancedir}/trace_clock
25562306a36Sopenharmony_ci	set_value_of ${instance}.cpumask ${instancedir}/tracing_cpumask
25662306a36Sopenharmony_ci	set_value_of ${instance}.tracing_on ${instancedir}/tracing_on
25762306a36Sopenharmony_ci	set_value_of ${instance}.tracer ${instancedir}/current_tracer
25862306a36Sopenharmony_ci	set_array_of ${instance}.ftrace.filters \
25962306a36Sopenharmony_ci		${instancedir}/set_ftrace_filter
26062306a36Sopenharmony_ci	set_array_of ${instance}.ftrace.notrace \
26162306a36Sopenharmony_ci		${instancedir}/set_ftrace_notrace
26262306a36Sopenharmony_ci
26362306a36Sopenharmony_ci	if xbc_has_key ${instance}.alloc_snapshot; then
26462306a36Sopenharmony_ci		run_cmd "echo 1 > ${instancedir}/snapshot"
26562306a36Sopenharmony_ci	fi
26662306a36Sopenharmony_ci
26762306a36Sopenharmony_ci	if xbc_has_key ${instance}.buffer_size; then
26862306a36Sopenharmony_ci		size=`xbc_get_val ${instance}.buffer_size 1`
26962306a36Sopenharmony_ci		size=`eval size2kb $size`
27062306a36Sopenharmony_ci		run_cmd "echo $size >> ${instancedir}/buffer_size_kb"
27162306a36Sopenharmony_ci	fi
27262306a36Sopenharmony_ci
27362306a36Sopenharmony_ci	setup_events ${instance} $1
27462306a36Sopenharmony_ci	set_array_of ${instance}.events ${instancedir}/set_event
27562306a36Sopenharmony_ci}
27662306a36Sopenharmony_ci
27762306a36Sopenharmony_ci# ftrace global configs (kernel.*)
27862306a36Sopenharmony_ciif xbc_has_key "kernel.dump_on_oops"; then
27962306a36Sopenharmony_ci	dump_mode=`xbc_get_val "kernel.dump_on_oops" 1`
28062306a36Sopenharmony_ci	[ "$dump_mode" ] && dump_mode=`eval echo $dump_mode` || dump_mode=1
28162306a36Sopenharmony_ci	run_cmd "echo \"$dump_mode\" > /proc/sys/kernel/ftrace_dump_on_oops"
28262306a36Sopenharmony_cifi
28362306a36Sopenharmony_ci
28462306a36Sopenharmony_ciset_value_of kernel.fgraph_max_depth $TRACEFS/max_graph_depth
28562306a36Sopenharmony_ciset_array_of kernel.fgraph_filters $TRACEFS/set_graph_function
28662306a36Sopenharmony_ciset_array_of kernel.fgraph_notraces $TRACEFS/set_graph_notrace
28762306a36Sopenharmony_ci
28862306a36Sopenharmony_ci# Per-instance/per-event configs
28962306a36Sopenharmony_ciif ! xbc_has_branch "ftrace" ; then
29062306a36Sopenharmony_ci	exit 0
29162306a36Sopenharmony_cifi
29262306a36Sopenharmony_ci
29362306a36Sopenharmony_cisetup_instance # root instance
29462306a36Sopenharmony_ci
29562306a36Sopenharmony_ciif xbc_has_branch "ftrace.instance"; then
29662306a36Sopenharmony_ci	for i in `xbc_subkeys "ftrace.instance" 1`; do
29762306a36Sopenharmony_ci		run_cmd "mkdir -p $TRACEFS/instances/$i"
29862306a36Sopenharmony_ci		setup_instance $i
29962306a36Sopenharmony_ci	done
30062306a36Sopenharmony_cifi
30162306a36Sopenharmony_ci
302