302 lines · bash
1#!/bin/sh2# SPDX-License-Identifier: GPL-2.0-only3 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 110}11 12[ $# -eq 0 ] && usage13 14BCONF=15DEBUG=16APPLY=17INIT=18while [ x"$1" != x ]; do19 case "$1" in20 "--debug")21 DEBUG=$1;;22 "--apply")23 APPLY=$1;;24 "--init")25 APPLY=$126 INIT=$1;;27 *)28 [ ! -f $1 ] && usage29 BCONF=$1;;30 esac31 shift 132done33 34if [ x"$APPLY" != x ]; then35 if [ `id -u` -ne 0 ]; then36 echo "This must be run by root user. Try sudo." 1>&237 exec sudo $0 $DEBUG $APPLY $BCONF38 fi39fi40 41run_cmd() { # command42 echo "$*"43 if [ x"$APPLY" != x ]; then # apply command44 eval $*45 fi46}47 48if [ x"$DEBUG" != x ]; then49 set -x50fi51 52TRACEFS=`grep -m 1 -w tracefs /proc/mounts | cut -f 2 -d " "`53if [ -z "$TRACEFS" ]; then54 if ! grep -wq debugfs /proc/mounts; then55 echo "Error: No tracefs/debugfs was mounted." 1>&256 exit 157 fi58 TRACEFS=`grep -m 1 -w debugfs /proc/mounts | cut -f 2 -d " "`/tracing59 if [ ! -d $TRACEFS ]; then60 echo "Error: ftrace is not enabled on this kernel." 1>&261 exit 162 fi63fi64 65if [ x"$INIT" != x ]; then66 . `dirname $0`/ftrace.sh67 (cd $TRACEFS; initialize_ftrace)68fi69 70. `dirname $0`/xbc.sh71 72######## main #########73set -e74 75xbc_init $BCONF76 77set_value_of() { # key file78 if xbc_has_key $1; then79 val=`xbc_get_val $1 1`80 run_cmd "echo '$val' >> $2"81 fi82}83 84set_array_of() { # key file85 if xbc_has_key $1; then86 xbc_get_val $1 | while read line; do87 run_cmd "echo '$line' >> $2"88 done89 fi90}91 92compose_synth() { # event_name branch93 echo -n "$1 "94 xbc_get_val $2 | while read field; do echo -n "$field; "; done95}96 97print_hist_array() { # prefix key98 __sep="="99 if xbc_has_key ${1}.${2}; then100 echo -n ":$2"101 xbc_get_val ${1}.${2} | while read field; do102 echo -n "$__sep$field"; __sep=","103 done104 fi105}106 107print_hist_action_array() { # prefix key108 __sep="("109 echo -n ".$2"110 xbc_get_val ${1}.${2} | while read field; do111 echo -n "$__sep$field"; __sep=","112 done113 echo -n ")"114}115 116print_hist_one_action() { # prefix handler param117 echo -n ":${2}("`xbc_get_val ${1}.${3}`")"118 if xbc_has_key "${1}.trace"; then119 print_hist_action_array ${1} "trace"120 elif xbc_has_key "${1}.save"; then121 print_hist_action_array ${1} "save"122 elif xbc_has_key "${1}.snapshot"; then123 echo -n ".snapshot()"124 fi125}126 127print_hist_actions() { # prefix handler param128 for __hdr in `xbc_subkeys ${1}.${2} 1 ".[0-9]"`; do129 print_hist_one_action ${1}.${2}.$__hdr ${2} ${3}130 done131 if xbc_has_key ${1}.${2}.${3} ; then132 print_hist_one_action ${1}.${2} ${2} ${3}133 fi134}135 136print_hist_var() { # prefix varname137 echo -n ":${2}="`xbc_get_val ${1}.var.${2} | tr -d [:space:]`138}139 140print_one_histogram() { # prefix141 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"; then146 echo -n ":size="`xbc_get_val ${1}.size`147 fi148 if xbc_has_key "${1}.name"; then149 echo -n ":name="`xbc_get_val ${1}.name`150 fi151 for __var in `xbc_subkeys "${1}.var" 1`; do152 print_hist_var ${1} ${__var}153 done154 if xbc_has_key "${1}.pause"; then155 echo -n ":pause"156 elif xbc_has_key "${1}.continue"; then157 echo -n ":continue"158 elif xbc_has_key "${1}.clear"; then159 echo -n ":clear"160 fi161 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"; then166 echo -n " if "`xbc_get_val ${1}.filter`167 fi168}169 170setup_one_histogram() { # prefix trigger-file171 run_cmd "echo '`print_one_histogram ${1}`' >> ${2}"172}173 174setup_histograms() { # prefix trigger-file175 for __hist in `xbc_subkeys ${1} 1 ".[0-9]"`; do176 setup_one_histogram ${1}.$__hist ${2}177 done178 if xbc_has_key ${1}.keys; then179 setup_one_histogram ${1} ${2}180 fi181}182 183setup_event() { # prefix group event [instance]184 branch=$1.$2.$3185 if [ "$4" ]; then186 eventdir="$TRACEFS/instances/$4/events/$2/$3"187 else188 eventdir="$TRACEFS/events/$2/$3"189 fi190 # group enable191 if [ "$3" = "enable" ]; then192 run_cmd "echo 1 > ${eventdir}"193 return194 fi195 196 case $2 in197 kprobes)198 xbc_get_val ${branch}.probes | while read line; do199 run_cmd "echo 'p:kprobes/$3 $line' >> $TRACEFS/kprobe_events"200 done201 ;;202 synthetic)203 run_cmd "echo '`compose_synth $3 ${branch}.fields`' >> $TRACEFS/synthetic_events"204 ;;205 esac206 207 set_value_of ${branch}.filter ${eventdir}/filter208 set_array_of ${branch}.actions ${eventdir}/trigger209 210 setup_histograms ${branch}.hist ${eventdir}/trigger211 212 if xbc_has_key ${branch}.enable; then213 run_cmd "echo 1 > ${eventdir}/enable"214 fi215}216 217setup_events() { # prefix("ftrace" or "ftrace.instance.INSTANCE") [instance]218 prefix="${1}.event"219 if xbc_has_branch ${1}.event; then220 for grpev in `xbc_subkeys ${1}.event 2`; do221 setup_event $prefix ${grpev%.*} ${grpev#*.} $2222 done223 fi224 if xbc_has_branch ${1}.event.enable; then225 if [ "$2" ]; then226 run_cmd "echo 1 > $TRACEFS/instances/$2/events/enable"227 else228 run_cmd "echo 1 > $TRACEFS/events/enable"229 fi230 fi231}232 233size2kb() { # size[KB|MB]234 case $1 in235 *KB)236 echo ${1%KB};;237 *MB)238 expr ${1%MB} \* 1024;;239 *)240 expr $1 / 1024 ;;241 esac242}243 244setup_instance() { # [instance]245 if [ "$1" ]; then246 instance="ftrace.instance.${1}"247 instancedir=$TRACEFS/instances/$1248 else249 instance="ftrace"250 instancedir=$TRACEFS251 fi252 253 set_array_of ${instance}.options ${instancedir}/trace_options254 set_value_of ${instance}.trace_clock ${instancedir}/trace_clock255 set_value_of ${instance}.cpumask ${instancedir}/tracing_cpumask256 set_value_of ${instance}.tracing_on ${instancedir}/tracing_on257 set_value_of ${instance}.tracer ${instancedir}/current_tracer258 set_array_of ${instance}.ftrace.filters \259 ${instancedir}/set_ftrace_filter260 set_array_of ${instance}.ftrace.notrace \261 ${instancedir}/set_ftrace_notrace262 263 if xbc_has_key ${instance}.alloc_snapshot; then264 run_cmd "echo 1 > ${instancedir}/snapshot"265 fi266 267 if xbc_has_key ${instance}.buffer_size; then268 size=`xbc_get_val ${instance}.buffer_size 1`269 size=`eval size2kb $size`270 run_cmd "echo $size >> ${instancedir}/buffer_size_kb"271 fi272 273 setup_events ${instance} $1274 set_array_of ${instance}.events ${instancedir}/set_event275}276 277# ftrace global configs (kernel.*)278if xbc_has_key "kernel.dump_on_oops"; then279 dump_mode=`xbc_get_val "kernel.dump_on_oops" 1`280 [ "$dump_mode" ] && dump_mode=`eval echo $dump_mode` || dump_mode=1281 run_cmd "echo \"$dump_mode\" > /proc/sys/kernel/ftrace_dump_on_oops"282fi283 284set_value_of kernel.fgraph_max_depth $TRACEFS/max_graph_depth285set_array_of kernel.fgraph_filters $TRACEFS/set_graph_function286set_array_of kernel.fgraph_notraces $TRACEFS/set_graph_notrace287 288# Per-instance/per-event configs289if ! xbc_has_branch "ftrace" ; then290 exit 0291fi292 293setup_instance # root instance294 295if xbc_has_branch "ftrace.instance"; then296 for i in `xbc_subkeys "ftrace.instance" 1`; do297 run_cmd "mkdir -p $TRACEFS/instances/$i"298 setup_instance $i299 done300fi301 302