1#!/bin/sh 2# SPDX-License-Identifier: GPL-2.0-only 3 4usage() { 5 echo "Ftrace boottime trace test tool" 6 echo "Usage: $0 [--apply|--init] [--debug] BOOTCONFIG-FILE" 7 echo " --apply: Test actual apply to tracefs (need sudo)" 8 echo " --init: Initialize ftrace before applying (imply --apply)" 9 exit 1 10} 11 12[ $# -eq 0 ] && usage 13 14BCONF= 15DEBUG= 16APPLY= 17INIT= 18while [ x"$1" != x ]; do 19 case "$1" in 20 "--debug") 21 DEBUG=$1;; 22 "--apply") 23 APPLY=$1;; 24 "--init") 25 APPLY=$1 26 INIT=$1;; 27 *) 28 [ ! -f $1 ] && usage 29 BCONF=$1;; 30 esac 31 shift 1 32done 33 34if [ x"$APPLY" != x ]; then 35 if [ `id -u` -ne 0 ]; then 36 echo "This must be run by root user. Try sudo." 1>&2 37 exec sudo $0 $DEBUG $APPLY $BCONF 38 fi 39fi 40 41run_cmd() { # command 42 echo "$*" 43 if [ x"$APPLY" != x ]; then # apply command 44 eval $* 45 fi 46} 47 48if [ x"$DEBUG" != x ]; then 49 set -x 50fi 51 52TRACEFS=`grep -m 1 -w tracefs /proc/mounts | cut -f 2 -d " "` 53if [ -z "$TRACEFS" ]; then 54 if ! grep -wq debugfs /proc/mounts; then 55 echo "Error: No tracefs/debugfs was mounted." 1>&2 56 exit 1 57 fi 58 TRACEFS=`grep -m 1 -w debugfs /proc/mounts | cut -f 2 -d " "`/tracing 59 if [ ! -d $TRACEFS ]; then 60 echo "Error: ftrace is not enabled on this kernel." 1>&2 61 exit 1 62 fi 63fi 64 65if [ x"$INIT" != x ]; then 66 . `dirname $0`/ftrace.sh 67 (cd $TRACEFS; initialize_ftrace) 68fi 69 70. `dirname $0`/xbc.sh 71 72######## main ######### 73set -e 74 75xbc_init $BCONF 76 77set_value_of() { # key file 78 if xbc_has_key $1; then 79 val=`xbc_get_val $1 1` 80 run_cmd "echo '$val' >> $2" 81 fi 82} 83 84set_array_of() { # key file 85 if xbc_has_key $1; then 86 xbc_get_val $1 | while read line; do 87 run_cmd "echo '$line' >> $2" 88 done 89 fi 90} 91 92compose_synth() { # event_name branch 93 echo -n "$1 " 94 xbc_get_val $2 | while read field; do echo -n "$field; "; done 95} 96 97print_hist_array() { # prefix key 98 __sep="=" 99 if xbc_has_key ${1}.${2}; then 100 echo -n ":$2" 101 xbc_get_val ${1}.${2} | while read field; do 102 echo -n "$__sep$field"; __sep="," 103 done 104 fi 105} 106 107print_hist_action_array() { # prefix key 108 __sep="(" 109 echo -n ".$2" 110 xbc_get_val ${1}.${2} | while read field; do 111 echo -n "$__sep$field"; __sep="," 112 done 113 echo -n ")" 114} 115 116print_hist_one_action() { # prefix handler param 117 echo -n ":${2}("`xbc_get_val ${1}.${3}`")" 118 if xbc_has_key "${1}.trace"; then 119 print_hist_action_array ${1} "trace" 120 elif xbc_has_key "${1}.save"; then 121 print_hist_action_array ${1} "save" 122 elif xbc_has_key "${1}.snapshot"; then 123 echo -n ".snapshot()" 124 fi 125} 126 127print_hist_actions() { # prefix handler param 128 for __hdr in `xbc_subkeys ${1}.${2} 1 ".[0-9]"`; do 129 print_hist_one_action ${1}.${2}.$__hdr ${2} ${3} 130 done 131 if xbc_has_key ${1}.${2}.${3} ; then 132 print_hist_one_action ${1}.${2} ${2} ${3} 133 fi 134} 135 136print_hist_var() { # prefix varname 137 echo -n ":${2}="`xbc_get_val ${1}.var.${2} | tr -d [:space:]` 138} 139 140print_one_histogram() { # prefix 141 echo -n "hist" 142 print_hist_array $1 "keys" 143 print_hist_array $1 "values" 144 print_hist_array $1 "sort" 145 if xbc_has_key "${1}.size"; then 146 echo -n ":size="`xbc_get_val ${1}.size` 147 fi 148 if xbc_has_key "${1}.name"; then 149 echo -n ":name="`xbc_get_val ${1}.name` 150 fi 151 for __var in `xbc_subkeys "${1}.var" 1`; do 152 print_hist_var ${1} ${__var} 153 done 154 if xbc_has_key "${1}.pause"; then 155 echo -n ":pause" 156 elif xbc_has_key "${1}.continue"; then 157 echo -n ":continue" 158 elif xbc_has_key "${1}.clear"; then 159 echo -n ":clear" 160 fi 161 print_hist_actions ${1} "onmax" "var" 162 print_hist_actions ${1} "onchange" "var" 163 print_hist_actions ${1} "onmatch" "event" 164 165 if xbc_has_key "${1}.filter"; then 166 echo -n " if "`xbc_get_val ${1}.filter` 167 fi 168} 169 170setup_one_histogram() { # prefix trigger-file 171 run_cmd "echo '`print_one_histogram ${1}`' >> ${2}" 172} 173 174setup_histograms() { # prefix trigger-file 175 for __hist in `xbc_subkeys ${1} 1 ".[0-9]"`; do 176 setup_one_histogram ${1}.$__hist ${2} 177 done 178 if xbc_has_key ${1}.keys; then 179 setup_one_histogram ${1} ${2} 180 fi 181} 182 183setup_event() { # prefix group event [instance] 184 branch=$1.$2.$3 185 if [ "$4" ]; then 186 eventdir="$TRACEFS/instances/$4/events/$2/$3" 187 else 188 eventdir="$TRACEFS/events/$2/$3" 189 fi 190 # group enable 191 if [ "$3" = "enable" ]; then 192 run_cmd "echo 1 > ${eventdir}" 193 return 194 fi 195 196 case $2 in 197 kprobes) 198 xbc_get_val ${branch}.probes | while read line; do 199 run_cmd "echo 'p:kprobes/$3 $line' >> $TRACEFS/kprobe_events" 200 done 201 ;; 202 synthetic) 203 run_cmd "echo '`compose_synth $3 ${branch}.fields`' >> $TRACEFS/synthetic_events" 204 ;; 205 esac 206 207 set_value_of ${branch}.filter ${eventdir}/filter 208 set_array_of ${branch}.actions ${eventdir}/trigger 209 210 setup_histograms ${branch}.hist ${eventdir}/trigger 211 212 if xbc_has_key ${branch}.enable; then 213 run_cmd "echo 1 > ${eventdir}/enable" 214 fi 215} 216 217setup_events() { # prefix("ftrace" or "ftrace.instance.INSTANCE") [instance] 218 prefix="${1}.event" 219 if xbc_has_branch ${1}.event; then 220 for grpev in `xbc_subkeys ${1}.event 2`; do 221 setup_event $prefix ${grpev%.*} ${grpev#*.} $2 222 done 223 fi 224 if xbc_has_branch ${1}.event.enable; then 225 if [ "$2" ]; then 226 run_cmd "echo 1 > $TRACEFS/instances/$2/events/enable" 227 else 228 run_cmd "echo 1 > $TRACEFS/events/enable" 229 fi 230 fi 231} 232 233size2kb() { # size[KB|MB] 234 case $1 in 235 *KB) 236 echo ${1%KB};; 237 *MB) 238 expr ${1%MB} \* 1024;; 239 *) 240 expr $1 / 1024 ;; 241 esac 242} 243 244setup_instance() { # [instance] 245 if [ "$1" ]; then 246 instance="ftrace.instance.${1}" 247 instancedir=$TRACEFS/instances/$1 248 else 249 instance="ftrace" 250 instancedir=$TRACEFS 251 fi 252 253 set_array_of ${instance}.options ${instancedir}/trace_options 254 set_value_of ${instance}.trace_clock ${instancedir}/trace_clock 255 set_value_of ${instance}.cpumask ${instancedir}/tracing_cpumask 256 set_value_of ${instance}.tracing_on ${instancedir}/tracing_on 257 set_value_of ${instance}.tracer ${instancedir}/current_tracer 258 set_array_of ${instance}.ftrace.filters \ 259 ${instancedir}/set_ftrace_filter 260 set_array_of ${instance}.ftrace.notrace \ 261 ${instancedir}/set_ftrace_notrace 262 263 if xbc_has_key ${instance}.alloc_snapshot; then 264 run_cmd "echo 1 > ${instancedir}/snapshot" 265 fi 266 267 if xbc_has_key ${instance}.buffer_size; then 268 size=`xbc_get_val ${instance}.buffer_size 1` 269 size=`eval size2kb $size` 270 run_cmd "echo $size >> ${instancedir}/buffer_size_kb" 271 fi 272 273 setup_events ${instance} $1 274 set_array_of ${instance}.events ${instancedir}/set_event 275} 276 277# ftrace global configs (kernel.*) 278if xbc_has_key "kernel.dump_on_oops"; then 279 dump_mode=`xbc_get_val "kernel.dump_on_oops" 1` 280 [ "$dump_mode" ] && dump_mode=`eval echo $dump_mode` || dump_mode=1 281 run_cmd "echo \"$dump_mode\" > /proc/sys/kernel/ftrace_dump_on_oops" 282fi 283 284set_value_of kernel.fgraph_max_depth $TRACEFS/max_graph_depth 285set_array_of kernel.fgraph_filters $TRACEFS/set_graph_function 286set_array_of kernel.fgraph_notraces $TRACEFS/set_graph_notrace 287 288# Per-instance/per-event configs 289if ! xbc_has_branch "ftrace" ; then 290 exit 0 291fi 292 293setup_instance # root instance 294 295if xbc_has_branch "ftrace.instance"; then 296 for i in `xbc_subkeys "ftrace.instance" 1`; do 297 run_cmd "mkdir -p $TRACEFS/instances/$i" 298 setup_instance $i 299 done 300fi 301 302