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