xref: /OK3568_Linux_fs/kernel/tools/perf/perf-with-kcore.sh (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun#!/bin/bash
2*4882a593Smuzhiyun# SPDX-License-Identifier: GPL-2.0-only
3*4882a593Smuzhiyun# perf-with-kcore: use perf with a copy of kcore
4*4882a593Smuzhiyun# Copyright (c) 2014, Intel Corporation.
5*4882a593Smuzhiyun#
6*4882a593Smuzhiyun
7*4882a593Smuzhiyunset -e
8*4882a593Smuzhiyun
9*4882a593Smuzhiyunusage()
10*4882a593Smuzhiyun{
11*4882a593Smuzhiyun        echo "Usage: perf-with-kcore <perf sub-command> <perf.data directory> [<sub-command options> [ -- <workload>]]" >&2
12*4882a593Smuzhiyun        echo "       <perf sub-command> can be record, script, report or inject" >&2
13*4882a593Smuzhiyun        echo "   or: perf-with-kcore fix_buildid_cache_permissions" >&2
14*4882a593Smuzhiyun        exit 1
15*4882a593Smuzhiyun}
16*4882a593Smuzhiyun
17*4882a593Smuzhiyunfind_perf()
18*4882a593Smuzhiyun{
19*4882a593Smuzhiyun	if [ -n "$PERF" ] ; then
20*4882a593Smuzhiyun		return
21*4882a593Smuzhiyun	fi
22*4882a593Smuzhiyun	PERF=`which perf || true`
23*4882a593Smuzhiyun	if [ -z "$PERF" ] ; then
24*4882a593Smuzhiyun		echo "Failed to find perf" >&2
25*4882a593Smuzhiyun	        exit 1
26*4882a593Smuzhiyun	fi
27*4882a593Smuzhiyun	if [ ! -x "$PERF" ] ; then
28*4882a593Smuzhiyun		echo "Failed to find perf" >&2
29*4882a593Smuzhiyun	        exit 1
30*4882a593Smuzhiyun	fi
31*4882a593Smuzhiyun	echo "Using $PERF"
32*4882a593Smuzhiyun	"$PERF" version
33*4882a593Smuzhiyun}
34*4882a593Smuzhiyun
35*4882a593Smuzhiyuncopy_kcore()
36*4882a593Smuzhiyun{
37*4882a593Smuzhiyun	echo "Copying kcore"
38*4882a593Smuzhiyun
39*4882a593Smuzhiyun	if [ $EUID -eq 0 ] ; then
40*4882a593Smuzhiyun		SUDO=""
41*4882a593Smuzhiyun	else
42*4882a593Smuzhiyun		SUDO="sudo"
43*4882a593Smuzhiyun	fi
44*4882a593Smuzhiyun
45*4882a593Smuzhiyun	rm -f perf.data.junk
46*4882a593Smuzhiyun	("$PERF" record -o perf.data.junk "${PERF_OPTIONS[@]}" -- sleep 60) >/dev/null 2>/dev/null &
47*4882a593Smuzhiyun	PERF_PID=$!
48*4882a593Smuzhiyun
49*4882a593Smuzhiyun	# Need to make sure that perf has started
50*4882a593Smuzhiyun	sleep 1
51*4882a593Smuzhiyun
52*4882a593Smuzhiyun	KCORE=$(($SUDO "$PERF" buildid-cache -v -f -k /proc/kcore >/dev/null) 2>&1)
53*4882a593Smuzhiyun	case "$KCORE" in
54*4882a593Smuzhiyun	"kcore added to build-id cache directory "*)
55*4882a593Smuzhiyun		KCORE_DIR=${KCORE#"kcore added to build-id cache directory "}
56*4882a593Smuzhiyun	;;
57*4882a593Smuzhiyun	*)
58*4882a593Smuzhiyun		kill $PERF_PID
59*4882a593Smuzhiyun		wait >/dev/null 2>/dev/null || true
60*4882a593Smuzhiyun		rm perf.data.junk
61*4882a593Smuzhiyun		echo "$KCORE"
62*4882a593Smuzhiyun		echo "Failed to find kcore" >&2
63*4882a593Smuzhiyun		exit 1
64*4882a593Smuzhiyun	;;
65*4882a593Smuzhiyun	esac
66*4882a593Smuzhiyun
67*4882a593Smuzhiyun	kill $PERF_PID
68*4882a593Smuzhiyun	wait >/dev/null 2>/dev/null || true
69*4882a593Smuzhiyun	rm perf.data.junk
70*4882a593Smuzhiyun
71*4882a593Smuzhiyun	$SUDO cp -a "$KCORE_DIR" "$(pwd)/$PERF_DATA_DIR"
72*4882a593Smuzhiyun	$SUDO rm -f "$KCORE_DIR/kcore"
73*4882a593Smuzhiyun	$SUDO rm -f "$KCORE_DIR/kallsyms"
74*4882a593Smuzhiyun	$SUDO rm -f "$KCORE_DIR/modules"
75*4882a593Smuzhiyun	$SUDO rmdir "$KCORE_DIR"
76*4882a593Smuzhiyun
77*4882a593Smuzhiyun	KCORE_DIR_BASENAME=$(basename "$KCORE_DIR")
78*4882a593Smuzhiyun	KCORE_DIR="$(pwd)/$PERF_DATA_DIR/$KCORE_DIR_BASENAME"
79*4882a593Smuzhiyun
80*4882a593Smuzhiyun	$SUDO chown $UID "$KCORE_DIR"
81*4882a593Smuzhiyun	$SUDO chown $UID "$KCORE_DIR/kcore"
82*4882a593Smuzhiyun	$SUDO chown $UID "$KCORE_DIR/kallsyms"
83*4882a593Smuzhiyun	$SUDO chown $UID "$KCORE_DIR/modules"
84*4882a593Smuzhiyun
85*4882a593Smuzhiyun	$SUDO chgrp $GROUPS "$KCORE_DIR"
86*4882a593Smuzhiyun	$SUDO chgrp $GROUPS "$KCORE_DIR/kcore"
87*4882a593Smuzhiyun	$SUDO chgrp $GROUPS "$KCORE_DIR/kallsyms"
88*4882a593Smuzhiyun	$SUDO chgrp $GROUPS "$KCORE_DIR/modules"
89*4882a593Smuzhiyun
90*4882a593Smuzhiyun	ln -s "$KCORE_DIR_BASENAME" "$PERF_DATA_DIR/kcore_dir"
91*4882a593Smuzhiyun}
92*4882a593Smuzhiyun
93*4882a593Smuzhiyunfix_buildid_cache_permissions()
94*4882a593Smuzhiyun{
95*4882a593Smuzhiyun	if [ $EUID -ne 0 ] ; then
96*4882a593Smuzhiyun		echo "This script must be run as root via sudo " >&2
97*4882a593Smuzhiyun		exit 1
98*4882a593Smuzhiyun	fi
99*4882a593Smuzhiyun
100*4882a593Smuzhiyun	if [ -z "$SUDO_USER" ] ; then
101*4882a593Smuzhiyun		echo "This script must be run via sudo" >&2
102*4882a593Smuzhiyun		exit 1
103*4882a593Smuzhiyun	fi
104*4882a593Smuzhiyun
105*4882a593Smuzhiyun	USER_HOME=$(bash <<< "echo ~$SUDO_USER")
106*4882a593Smuzhiyun
107*4882a593Smuzhiyun	echo "Fixing buildid cache permissions"
108*4882a593Smuzhiyun
109*4882a593Smuzhiyun	find "$USER_HOME/.debug" -xdev -type d          ! -user "$SUDO_USER" -ls -exec chown    "$SUDO_USER" \{\} \;
110*4882a593Smuzhiyun	find "$USER_HOME/.debug" -xdev -type f -links 1 ! -user "$SUDO_USER" -ls -exec chown    "$SUDO_USER" \{\} \;
111*4882a593Smuzhiyun	find "$USER_HOME/.debug" -xdev -type l          ! -user "$SUDO_USER" -ls -exec chown -h "$SUDO_USER" \{\} \;
112*4882a593Smuzhiyun
113*4882a593Smuzhiyun	if [ -n "$SUDO_GID" ] ; then
114*4882a593Smuzhiyun		find "$USER_HOME/.debug" -xdev -type d          ! -group "$SUDO_GID" -ls -exec chgrp    "$SUDO_GID" \{\} \;
115*4882a593Smuzhiyun		find "$USER_HOME/.debug" -xdev -type f -links 1 ! -group "$SUDO_GID" -ls -exec chgrp    "$SUDO_GID" \{\} \;
116*4882a593Smuzhiyun		find "$USER_HOME/.debug" -xdev -type l          ! -group "$SUDO_GID" -ls -exec chgrp -h "$SUDO_GID" \{\} \;
117*4882a593Smuzhiyun	fi
118*4882a593Smuzhiyun
119*4882a593Smuzhiyun	echo "Done"
120*4882a593Smuzhiyun}
121*4882a593Smuzhiyun
122*4882a593Smuzhiyuncheck_buildid_cache_permissions()
123*4882a593Smuzhiyun{
124*4882a593Smuzhiyun	if [ $EUID -eq 0 ] ; then
125*4882a593Smuzhiyun		return
126*4882a593Smuzhiyun	fi
127*4882a593Smuzhiyun
128*4882a593Smuzhiyun	PERMISSIONS_OK+=$(find "$HOME/.debug" -xdev -type d          ! -user "$USER" -print -quit)
129*4882a593Smuzhiyun	PERMISSIONS_OK+=$(find "$HOME/.debug" -xdev -type f -links 1 ! -user "$USER" -print -quit)
130*4882a593Smuzhiyun	PERMISSIONS_OK+=$(find "$HOME/.debug" -xdev -type l          ! -user "$USER" -print -quit)
131*4882a593Smuzhiyun
132*4882a593Smuzhiyun	PERMISSIONS_OK+=$(find "$HOME/.debug" -xdev -type d          ! -group "$GROUPS" -print -quit)
133*4882a593Smuzhiyun	PERMISSIONS_OK+=$(find "$HOME/.debug" -xdev -type f -links 1 ! -group "$GROUPS" -print -quit)
134*4882a593Smuzhiyun	PERMISSIONS_OK+=$(find "$HOME/.debug" -xdev -type l          ! -group "$GROUPS" -print -quit)
135*4882a593Smuzhiyun
136*4882a593Smuzhiyun	if [ -n "$PERMISSIONS_OK" ] ; then
137*4882a593Smuzhiyun		echo "*** WARNING *** buildid cache permissions may need fixing" >&2
138*4882a593Smuzhiyun	fi
139*4882a593Smuzhiyun}
140*4882a593Smuzhiyun
141*4882a593Smuzhiyunrecord()
142*4882a593Smuzhiyun{
143*4882a593Smuzhiyun	echo "Recording"
144*4882a593Smuzhiyun
145*4882a593Smuzhiyun	if [ $EUID -ne 0 ] ; then
146*4882a593Smuzhiyun
147*4882a593Smuzhiyun		if [ "$(cat /proc/sys/kernel/kptr_restrict)" -ne 0 ] ; then
148*4882a593Smuzhiyun			echo "*** WARNING *** /proc/sys/kernel/kptr_restrict prevents access to kernel addresses" >&2
149*4882a593Smuzhiyun		fi
150*4882a593Smuzhiyun
151*4882a593Smuzhiyun		if echo "${PERF_OPTIONS[@]}" | grep -q ' -a \|^-a \| -a$\|^-a$\| --all-cpus \|^--all-cpus \| --all-cpus$\|^--all-cpus$' ; then
152*4882a593Smuzhiyun			echo "*** WARNING *** system-wide tracing without root access will not be able to read all necessary information from /proc" >&2
153*4882a593Smuzhiyun		fi
154*4882a593Smuzhiyun
155*4882a593Smuzhiyun		if echo "${PERF_OPTIONS[@]}" | grep -q 'intel_pt\|intel_bts\| -I\|^-I' ; then
156*4882a593Smuzhiyun			if [ "$(cat /proc/sys/kernel/perf_event_paranoid)" -gt -1 ] ; then
157*4882a593Smuzhiyun				echo "*** WARNING *** /proc/sys/kernel/perf_event_paranoid restricts buffer size and tracepoint (sched_switch) use" >&2
158*4882a593Smuzhiyun			fi
159*4882a593Smuzhiyun
160*4882a593Smuzhiyun			if echo "${PERF_OPTIONS[@]}" | grep -q ' --per-thread \|^--per-thread \| --per-thread$\|^--per-thread$' ; then
161*4882a593Smuzhiyun				true
162*4882a593Smuzhiyun			elif echo "${PERF_OPTIONS[@]}" | grep -q ' -t \|^-t \| -t$\|^-t$' ; then
163*4882a593Smuzhiyun				true
164*4882a593Smuzhiyun			elif [ ! -r /sys/kernel/debug -o ! -x /sys/kernel/debug ] ; then
165*4882a593Smuzhiyun				echo "*** WARNING *** /sys/kernel/debug permissions prevent tracepoint (sched_switch) use" >&2
166*4882a593Smuzhiyun			fi
167*4882a593Smuzhiyun		fi
168*4882a593Smuzhiyun	fi
169*4882a593Smuzhiyun
170*4882a593Smuzhiyun	if [ -z "$1" ] ; then
171*4882a593Smuzhiyun		echo "Workload is required for recording" >&2
172*4882a593Smuzhiyun		usage
173*4882a593Smuzhiyun	fi
174*4882a593Smuzhiyun
175*4882a593Smuzhiyun	if [ -e "$PERF_DATA_DIR" ] ; then
176*4882a593Smuzhiyun		echo "'$PERF_DATA_DIR' exists" >&2
177*4882a593Smuzhiyun		exit 1
178*4882a593Smuzhiyun	fi
179*4882a593Smuzhiyun
180*4882a593Smuzhiyun	find_perf
181*4882a593Smuzhiyun
182*4882a593Smuzhiyun	mkdir "$PERF_DATA_DIR"
183*4882a593Smuzhiyun
184*4882a593Smuzhiyun	echo "$PERF record -o $PERF_DATA_DIR/perf.data ${PERF_OPTIONS[@]} -- $@"
185*4882a593Smuzhiyun	"$PERF" record -o "$PERF_DATA_DIR/perf.data" "${PERF_OPTIONS[@]}" -- "$@" || true
186*4882a593Smuzhiyun
187*4882a593Smuzhiyun	if rmdir "$PERF_DATA_DIR" > /dev/null 2>/dev/null ; then
188*4882a593Smuzhiyun		exit 1
189*4882a593Smuzhiyun	fi
190*4882a593Smuzhiyun
191*4882a593Smuzhiyun	copy_kcore
192*4882a593Smuzhiyun
193*4882a593Smuzhiyun	echo "Done"
194*4882a593Smuzhiyun}
195*4882a593Smuzhiyun
196*4882a593Smuzhiyunsubcommand()
197*4882a593Smuzhiyun{
198*4882a593Smuzhiyun	find_perf
199*4882a593Smuzhiyun	check_buildid_cache_permissions
200*4882a593Smuzhiyun	echo "$PERF $PERF_SUB_COMMAND -i $PERF_DATA_DIR/perf.data --kallsyms=$PERF_DATA_DIR/kcore_dir/kallsyms $@"
201*4882a593Smuzhiyun	"$PERF" $PERF_SUB_COMMAND -i "$PERF_DATA_DIR/perf.data" "--kallsyms=$PERF_DATA_DIR/kcore_dir/kallsyms" "$@"
202*4882a593Smuzhiyun}
203*4882a593Smuzhiyun
204*4882a593Smuzhiyunif [ "$1" = "fix_buildid_cache_permissions" ] ; then
205*4882a593Smuzhiyun	fix_buildid_cache_permissions
206*4882a593Smuzhiyun	exit 0
207*4882a593Smuzhiyunfi
208*4882a593Smuzhiyun
209*4882a593SmuzhiyunPERF_SUB_COMMAND=$1
210*4882a593SmuzhiyunPERF_DATA_DIR=$2
211*4882a593Smuzhiyunshift || true
212*4882a593Smuzhiyunshift || true
213*4882a593Smuzhiyun
214*4882a593Smuzhiyunif [ -z "$PERF_SUB_COMMAND" ] ; then
215*4882a593Smuzhiyun	usage
216*4882a593Smuzhiyunfi
217*4882a593Smuzhiyun
218*4882a593Smuzhiyunif [ -z "$PERF_DATA_DIR" ] ; then
219*4882a593Smuzhiyun	usage
220*4882a593Smuzhiyunfi
221*4882a593Smuzhiyun
222*4882a593Smuzhiyuncase "$PERF_SUB_COMMAND" in
223*4882a593Smuzhiyun"record")
224*4882a593Smuzhiyun	while [ "$1" != "--" ] ; do
225*4882a593Smuzhiyun		PERF_OPTIONS+=("$1")
226*4882a593Smuzhiyun		shift || break
227*4882a593Smuzhiyun	done
228*4882a593Smuzhiyun	if [ "$1" != "--" ] ; then
229*4882a593Smuzhiyun		echo "Options and workload are required for recording" >&2
230*4882a593Smuzhiyun		usage
231*4882a593Smuzhiyun	fi
232*4882a593Smuzhiyun	shift
233*4882a593Smuzhiyun	record "$@"
234*4882a593Smuzhiyun;;
235*4882a593Smuzhiyun"script")
236*4882a593Smuzhiyun	subcommand "$@"
237*4882a593Smuzhiyun;;
238*4882a593Smuzhiyun"report")
239*4882a593Smuzhiyun	subcommand "$@"
240*4882a593Smuzhiyun;;
241*4882a593Smuzhiyun"inject")
242*4882a593Smuzhiyun	subcommand "$@"
243*4882a593Smuzhiyun;;
244*4882a593Smuzhiyun*)
245*4882a593Smuzhiyun	usage
246*4882a593Smuzhiyun;;
247*4882a593Smuzhiyunesac
248