summaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/perf/Documentation/Makefile86
-rw-r--r--tools/perf/Documentation/perf-lock.txt20
-rw-r--r--tools/perf/Documentation/perf-record.txt8
-rw-r--r--tools/perf/Documentation/perf-script.txt5
-rw-r--r--tools/perf/Documentation/perf-stat.txt4
-rw-r--r--tools/perf/Documentation/perf-top.txt8
-rw-r--r--tools/perf/MANIFEST1
-rw-r--r--tools/perf/Makefile12
-rw-r--r--tools/perf/bench/bench.h1
-rw-r--r--tools/perf/bench/mem-memcpy-x86-64-asm-def.h8
-rw-r--r--tools/perf/bench/mem-memcpy-x86-64-asm.S6
-rw-r--r--tools/perf/bench/mem-memcpy.c12
-rw-r--r--tools/perf/bench/mem-memset-arch.h12
-rw-r--r--tools/perf/bench/mem-memset-x86-64-asm-def.h12
-rw-r--r--tools/perf/bench/mem-memset-x86-64-asm.S13
-rw-r--r--tools/perf/bench/mem-memset.c297
-rw-r--r--tools/perf/builtin-bench.c3
-rw-r--r--tools/perf/builtin-lock.c4
-rw-r--r--tools/perf/builtin-probe.c12
-rw-r--r--tools/perf/builtin-record.c57
-rw-r--r--tools/perf/builtin-script.c80
-rw-r--r--tools/perf/builtin-stat.c41
-rw-r--r--tools/perf/builtin-test.c188
-rw-r--r--tools/perf/builtin-top.c45
-rw-r--r--tools/perf/perf.h8
-rwxr-xr-xtools/perf/python/twatch.py2
-rw-r--r--tools/perf/util/bitmap.c10
-rw-r--r--tools/perf/util/cpumap.c11
-rw-r--r--tools/perf/util/cpumap.h4
-rw-r--r--tools/perf/util/ctype.c2
-rw-r--r--tools/perf/util/debugfs.c141
-rw-r--r--tools/perf/util/debugfs.h6
-rw-r--r--tools/perf/util/evlist.c16
-rw-r--r--tools/perf/util/evlist.h9
-rw-r--r--tools/perf/util/evsel.c8
-rw-r--r--tools/perf/util/header.c421
-rw-r--r--tools/perf/util/header.h1
-rw-r--r--tools/perf/util/hist.h2
-rw-r--r--tools/perf/util/include/asm/dwarf2.h4
-rw-r--r--tools/perf/util/include/linux/bitmap.h11
-rw-r--r--tools/perf/util/map.c15
-rw-r--r--tools/perf/util/map.h1
-rw-r--r--tools/perf/util/probe-event.c33
-rw-r--r--tools/perf/util/probe-finder.c1
-rw-r--r--tools/perf/util/python-ext-sources19
-rw-r--r--tools/perf/util/python.c10
-rw-r--r--tools/perf/util/scripting-engines/trace-event-python.c1
-rw-r--r--tools/perf/util/session.c49
-rw-r--r--tools/perf/util/session.h2
-rw-r--r--tools/perf/util/setup.py8
-rw-r--r--tools/perf/util/symbol.c24
-rw-r--r--tools/perf/util/symbol.h4
-rw-r--r--tools/perf/util/sysfs.c60
-rw-r--r--tools/perf/util/sysfs.h6
-rw-r--r--tools/perf/util/thread_map.c237
-rw-r--r--tools/perf/util/thread_map.h11
-rw-r--r--tools/perf/util/top.c13
-rw-r--r--tools/perf/util/top.h6
-rw-r--r--tools/perf/util/trace-event-parse.c13
-rw-r--r--tools/perf/util/trace-event-read.c1
-rw-r--r--tools/perf/util/trace-event-scripting.c1
-rw-r--r--tools/perf/util/ui/browsers/hists.c3
-rw-r--r--tools/perf/util/ui/browsers/map.c2
-rw-r--r--tools/perf/util/usage.c39
-rw-r--r--tools/perf/util/util.c2
-rw-r--r--tools/perf/util/util.h6
66 files changed, 1601 insertions, 557 deletions
diff --git a/tools/perf/Documentation/Makefile b/tools/perf/Documentation/Makefile
index 4626a398836a..ca600e09c8d4 100644
--- a/tools/perf/Documentation/Makefile
+++ b/tools/perf/Documentation/Makefile
@@ -1,3 +1,10 @@
1OUTPUT := ./
2ifeq ("$(origin O)", "command line")
3 ifneq ($(O),)
4 OUTPUT := $(O)/
5 endif
6endif
7
1MAN1_TXT= \ 8MAN1_TXT= \
2 $(filter-out $(addsuffix .txt, $(ARTICLES) $(SP_ARTICLES)), \ 9 $(filter-out $(addsuffix .txt, $(ARTICLES) $(SP_ARTICLES)), \
3 $(wildcard perf-*.txt)) \ 10 $(wildcard perf-*.txt)) \
@@ -6,10 +13,11 @@ MAN5_TXT=
6MAN7_TXT= 13MAN7_TXT=
7 14
8MAN_TXT = $(MAN1_TXT) $(MAN5_TXT) $(MAN7_TXT) 15MAN_TXT = $(MAN1_TXT) $(MAN5_TXT) $(MAN7_TXT)
9MAN_XML=$(patsubst %.txt,%.xml,$(MAN_TXT)) 16_MAN_XML=$(patsubst %.txt,%.xml,$(MAN_TXT))
10MAN_HTML=$(patsubst %.txt,%.html,$(MAN_TXT)) 17_MAN_HTML=$(patsubst %.txt,%.html,$(MAN_TXT))
11 18
12DOC_HTML=$(MAN_HTML) 19MAN_XML=$(addprefix $(OUTPUT),$(_MAN_XML))
20MAN_HTML=$(addprefix $(OUTPUT),$(_MAN_HTML))
13 21
14ARTICLES = 22ARTICLES =
15# with their own formatting rules. 23# with their own formatting rules.
@@ -18,11 +26,17 @@ API_DOCS = $(patsubst %.txt,%,$(filter-out technical/api-index-skel.txt technica
18SP_ARTICLES += $(API_DOCS) 26SP_ARTICLES += $(API_DOCS)
19SP_ARTICLES += technical/api-index 27SP_ARTICLES += technical/api-index
20 28
21DOC_HTML += $(patsubst %,%.html,$(ARTICLES) $(SP_ARTICLES)) 29_DOC_HTML = $(_MAN_HTML)
30_DOC_HTML+=$(patsubst %,%.html,$(ARTICLES) $(SP_ARTICLES))
31DOC_HTML=$(addprefix $(OUTPUT),$(_DOC_HTML))
22 32
23DOC_MAN1=$(patsubst %.txt,%.1,$(MAN1_TXT)) 33_DOC_MAN1=$(patsubst %.txt,%.1,$(MAN1_TXT))
24DOC_MAN5=$(patsubst %.txt,%.5,$(MAN5_TXT)) 34_DOC_MAN5=$(patsubst %.txt,%.5,$(MAN5_TXT))
25DOC_MAN7=$(patsubst %.txt,%.7,$(MAN7_TXT)) 35_DOC_MAN7=$(patsubst %.txt,%.7,$(MAN7_TXT))
36
37DOC_MAN1=$(addprefix $(OUTPUT),$(_DOC_MAN1))
38DOC_MAN5=$(addprefix $(OUTPUT),$(_DOC_MAN5))
39DOC_MAN7=$(addprefix $(OUTPUT),$(_DOC_MAN7))
26 40
27# Make the path relative to DESTDIR, not prefix 41# Make the path relative to DESTDIR, not prefix
28ifndef DESTDIR 42ifndef DESTDIR
@@ -150,9 +164,9 @@ man1: $(DOC_MAN1)
150man5: $(DOC_MAN5) 164man5: $(DOC_MAN5)
151man7: $(DOC_MAN7) 165man7: $(DOC_MAN7)
152 166
153info: perf.info perfman.info 167info: $(OUTPUT)perf.info $(OUTPUT)perfman.info
154 168
155pdf: user-manual.pdf 169pdf: $(OUTPUT)user-manual.pdf
156 170
157install: install-man 171install: install-man
158 172
@@ -166,7 +180,7 @@ install-man: man
166 180
167install-info: info 181install-info: info
168 $(INSTALL) -d -m 755 $(DESTDIR)$(infodir) 182 $(INSTALL) -d -m 755 $(DESTDIR)$(infodir)
169 $(INSTALL) -m 644 perf.info perfman.info $(DESTDIR)$(infodir) 183 $(INSTALL) -m 644 $(OUTPUT)perf.info $(OUTPUT)perfman.info $(DESTDIR)$(infodir)
170 if test -r $(DESTDIR)$(infodir)/dir; then \ 184 if test -r $(DESTDIR)$(infodir)/dir; then \
171 $(INSTALL_INFO) --info-dir=$(DESTDIR)$(infodir) perf.info ;\ 185 $(INSTALL_INFO) --info-dir=$(DESTDIR)$(infodir) perf.info ;\
172 $(INSTALL_INFO) --info-dir=$(DESTDIR)$(infodir) perfman.info ;\ 186 $(INSTALL_INFO) --info-dir=$(DESTDIR)$(infodir) perfman.info ;\
@@ -176,7 +190,7 @@ install-info: info
176 190
177install-pdf: pdf 191install-pdf: pdf
178 $(INSTALL) -d -m 755 $(DESTDIR)$(pdfdir) 192 $(INSTALL) -d -m 755 $(DESTDIR)$(pdfdir)
179 $(INSTALL) -m 644 user-manual.pdf $(DESTDIR)$(pdfdir) 193 $(INSTALL) -m 644 $(OUTPUT)user-manual.pdf $(DESTDIR)$(pdfdir)
180 194
181#install-html: html 195#install-html: html
182# '$(SHELL_PATH_SQ)' ./install-webdoc.sh $(DESTDIR)$(htmldir) 196# '$(SHELL_PATH_SQ)' ./install-webdoc.sh $(DESTDIR)$(htmldir)
@@ -189,14 +203,14 @@ install-pdf: pdf
189# 203#
190# Determine "include::" file references in asciidoc files. 204# Determine "include::" file references in asciidoc files.
191# 205#
192doc.dep : $(wildcard *.txt) build-docdep.perl 206$(OUTPUT)doc.dep : $(wildcard *.txt) build-docdep.perl
193 $(QUIET_GEN)$(RM) $@+ $@ && \ 207 $(QUIET_GEN)$(RM) $@+ $@ && \
194 $(PERL_PATH) ./build-docdep.perl >$@+ $(QUIET_STDERR) && \ 208 $(PERL_PATH) ./build-docdep.perl >$@+ $(QUIET_STDERR) && \
195 mv $@+ $@ 209 mv $@+ $@
196 210
197-include doc.dep 211-include $(OUPTUT)doc.dep
198 212
199cmds_txt = cmds-ancillaryinterrogators.txt \ 213_cmds_txt = cmds-ancillaryinterrogators.txt \
200 cmds-ancillarymanipulators.txt \ 214 cmds-ancillarymanipulators.txt \
201 cmds-mainporcelain.txt \ 215 cmds-mainporcelain.txt \
202 cmds-plumbinginterrogators.txt \ 216 cmds-plumbinginterrogators.txt \
@@ -205,32 +219,36 @@ cmds_txt = cmds-ancillaryinterrogators.txt \
205 cmds-synchelpers.txt \ 219 cmds-synchelpers.txt \
206 cmds-purehelpers.txt \ 220 cmds-purehelpers.txt \
207 cmds-foreignscminterface.txt 221 cmds-foreignscminterface.txt
222cmds_txt=$(addprefix $(OUTPUT),$(_cmds_txt))
208 223
209$(cmds_txt): cmd-list.made 224$(cmds_txt): $(OUTPUT)cmd-list.made
210 225
211cmd-list.made: cmd-list.perl ../command-list.txt $(MAN1_TXT) 226$(OUTPUT)cmd-list.made: cmd-list.perl ../command-list.txt $(MAN1_TXT)
212 $(QUIET_GEN)$(RM) $@ && \ 227 $(QUIET_GEN)$(RM) $@ && \
213 $(PERL_PATH) ./cmd-list.perl ../command-list.txt $(QUIET_STDERR) && \ 228 $(PERL_PATH) ./cmd-list.perl ../command-list.txt $(QUIET_STDERR) && \
214 date >$@ 229 date >$@
215 230
216clean: 231clean:
217 $(RM) *.xml *.xml+ *.html *.html+ *.1 *.5 *.7 232 $(RM) $(MAN_XML) $(addsuffix +,$(MAN_XML))
218 $(RM) *.texi *.texi+ *.texi++ perf.info perfman.info 233 $(RM) $(MAN_HTML) $(addsuffix +,$(MAN_HTML))
219 $(RM) howto-index.txt howto/*.html doc.dep 234 $(RM) $(DOC_HTML) $(DOC_MAN1) $(DOC_MAN5) $(DOC_MAN7)
220 $(RM) technical/api-*.html technical/api-index.txt 235 $(RM) $(OUTPUT)*.texi $(OUTPUT)*.texi+ $(OUTPUT)*.texi++
221 $(RM) $(cmds_txt) *.made 236 $(RM) $(OUTPUT)perf.info $(OUTPUT)perfman.info
222 237 $(RM) $(OUTPUT)howto-index.txt $(OUTPUT)howto/*.html $(OUTPUT)doc.dep
223$(MAN_HTML): %.html : %.txt 238 $(RM) $(OUTPUT)technical/api-*.html $(OUTPUT)technical/api-index.txt
239 $(RM) $(cmds_txt) $(OUTPUT)*.made
240
241$(MAN_HTML): $(OUTPUT)%.html : %.txt
224 $(QUIET_ASCIIDOC)$(RM) $@+ $@ && \ 242 $(QUIET_ASCIIDOC)$(RM) $@+ $@ && \
225 $(ASCIIDOC) -b xhtml11 -d manpage -f asciidoc.conf \ 243 $(ASCIIDOC) -b xhtml11 -d manpage -f asciidoc.conf \
226 $(ASCIIDOC_EXTRA) -aperf_version=$(PERF_VERSION) -o $@+ $< && \ 244 $(ASCIIDOC_EXTRA) -aperf_version=$(PERF_VERSION) -o $@+ $< && \
227 mv $@+ $@ 245 mv $@+ $@
228 246
229%.1 %.5 %.7 : %.xml 247$(OUTPUT)%.1 $(OUTPUT)%.5 $(OUTPUT)%.7 : $(OUTPUT)%.xml
230 $(QUIET_XMLTO)$(RM) $@ && \ 248 $(QUIET_XMLTO)$(RM) $@ && \
231 xmlto -m $(MANPAGE_XSL) $(XMLTO_EXTRA) man $< 249 xmlto -o $(OUTPUT) -m $(MANPAGE_XSL) $(XMLTO_EXTRA) man $<
232 250
233%.xml : %.txt 251$(OUTPUT)%.xml : %.txt
234 $(QUIET_ASCIIDOC)$(RM) $@+ $@ && \ 252 $(QUIET_ASCIIDOC)$(RM) $@+ $@ && \
235 $(ASCIIDOC) -b docbook -d manpage -f asciidoc.conf \ 253 $(ASCIIDOC) -b docbook -d manpage -f asciidoc.conf \
236 $(ASCIIDOC_EXTRA) -aperf_version=$(PERF_VERSION) -o $@+ $< && \ 254 $(ASCIIDOC_EXTRA) -aperf_version=$(PERF_VERSION) -o $@+ $< && \
@@ -239,25 +257,25 @@ $(MAN_HTML): %.html : %.txt
239XSLT = docbook.xsl 257XSLT = docbook.xsl
240XSLTOPTS = --xinclude --stringparam html.stylesheet docbook-xsl.css 258XSLTOPTS = --xinclude --stringparam html.stylesheet docbook-xsl.css
241 259
242user-manual.html: user-manual.xml 260$(OUTPUT)user-manual.html: $(OUTPUT)user-manual.xml
243 $(QUIET_XSLTPROC)xsltproc $(XSLTOPTS) -o $@ $(XSLT) $< 261 $(QUIET_XSLTPROC)xsltproc $(XSLTOPTS) -o $@ $(XSLT) $<
244 262
245perf.info: user-manual.texi 263$(OUTPUT)perf.info: $(OUTPUT)user-manual.texi
246 $(QUIET_MAKEINFO)$(MAKEINFO) --no-split -o $@ user-manual.texi 264 $(QUIET_MAKEINFO)$(MAKEINFO) --no-split -o $@ $(OUTPUT)user-manual.texi
247 265
248user-manual.texi: user-manual.xml 266$(OUTPUT)user-manual.texi: $(OUTPUT)user-manual.xml
249 $(QUIET_DB2TEXI)$(RM) $@+ $@ && \ 267 $(QUIET_DB2TEXI)$(RM) $@+ $@ && \
250 $(DOCBOOK2X_TEXI) user-manual.xml --encoding=UTF-8 --to-stdout >$@++ && \ 268 $(DOCBOOK2X_TEXI) $(OUTPUT)user-manual.xml --encoding=UTF-8 --to-stdout >$@++ && \
251 $(PERL_PATH) fix-texi.perl <$@++ >$@+ && \ 269 $(PERL_PATH) fix-texi.perl <$@++ >$@+ && \
252 rm $@++ && \ 270 rm $@++ && \
253 mv $@+ $@ 271 mv $@+ $@
254 272
255user-manual.pdf: user-manual.xml 273$(OUTPUT)user-manual.pdf: $(OUTPUT)user-manual.xml
256 $(QUIET_DBLATEX)$(RM) $@+ $@ && \ 274 $(QUIET_DBLATEX)$(RM) $@+ $@ && \
257 $(DBLATEX) -o $@+ -p /etc/asciidoc/dblatex/asciidoc-dblatex.xsl -s /etc/asciidoc/dblatex/asciidoc-dblatex.sty $< && \ 275 $(DBLATEX) -o $@+ -p /etc/asciidoc/dblatex/asciidoc-dblatex.xsl -s /etc/asciidoc/dblatex/asciidoc-dblatex.sty $< && \
258 mv $@+ $@ 276 mv $@+ $@
259 277
260perfman.texi: $(MAN_XML) cat-texi.perl 278$(OUTPUT)perfman.texi: $(MAN_XML) cat-texi.perl
261 $(QUIET_DB2TEXI)$(RM) $@+ $@ && \ 279 $(QUIET_DB2TEXI)$(RM) $@+ $@ && \
262 ($(foreach xml,$(MAN_XML),$(DOCBOOK2X_TEXI) --encoding=UTF-8 \ 280 ($(foreach xml,$(MAN_XML),$(DOCBOOK2X_TEXI) --encoding=UTF-8 \
263 --to-stdout $(xml) &&) true) > $@++ && \ 281 --to-stdout $(xml) &&) true) > $@++ && \
@@ -265,7 +283,7 @@ perfman.texi: $(MAN_XML) cat-texi.perl
265 rm $@++ && \ 283 rm $@++ && \
266 mv $@+ $@ 284 mv $@+ $@
267 285
268perfman.info: perfman.texi 286$(OUTPUT)perfman.info: $(OUTPUT)perfman.texi
269 $(QUIET_MAKEINFO)$(MAKEINFO) --no-split --no-validate $*.texi 287 $(QUIET_MAKEINFO)$(MAKEINFO) --no-split --no-validate $*.texi
270 288
271$(patsubst %.txt,%.texi,$(MAN_TXT)): %.texi : %.xml 289$(patsubst %.txt,%.texi,$(MAN_TXT)): %.texi : %.xml
diff --git a/tools/perf/Documentation/perf-lock.txt b/tools/perf/Documentation/perf-lock.txt
index d6b2a4f2108b..c7f5f55634ac 100644
--- a/tools/perf/Documentation/perf-lock.txt
+++ b/tools/perf/Documentation/perf-lock.txt
@@ -8,7 +8,7 @@ perf-lock - Analyze lock events
8SYNOPSIS 8SYNOPSIS
9-------- 9--------
10[verse] 10[verse]
11'perf lock' {record|report|trace} 11'perf lock' {record|report|script|info}
12 12
13DESCRIPTION 13DESCRIPTION
14----------- 14-----------
@@ -20,10 +20,13 @@ and statistics with this 'perf lock' command.
20 produces the file "perf.data" which contains tracing 20 produces the file "perf.data" which contains tracing
21 results of lock events. 21 results of lock events.
22 22
23 'perf lock trace' shows raw lock events.
24
25 'perf lock report' reports statistical data. 23 'perf lock report' reports statistical data.
26 24
25 'perf lock script' shows raw lock events.
26
27 'perf lock info' shows metadata like threads or addresses
28 of lock instances.
29
27COMMON OPTIONS 30COMMON OPTIONS
28-------------- 31--------------
29 32
@@ -47,6 +50,17 @@ REPORT OPTIONS
47 Sorting key. Possible values: acquired (default), contended, 50 Sorting key. Possible values: acquired (default), contended,
48 wait_total, wait_max, wait_min. 51 wait_total, wait_max, wait_min.
49 52
53INFO OPTIONS
54------------
55
56-t::
57--threads::
58 dump thread list in perf.data
59
60-m::
61--map::
62 dump map of lock instances (address:name table)
63
50SEE ALSO 64SEE ALSO
51-------- 65--------
52linkperf:perf[1] 66linkperf:perf[1]
diff --git a/tools/perf/Documentation/perf-record.txt b/tools/perf/Documentation/perf-record.txt
index 2937f7e14bb7..a5766b4b0125 100644
--- a/tools/perf/Documentation/perf-record.txt
+++ b/tools/perf/Documentation/perf-record.txt
@@ -52,11 +52,15 @@ OPTIONS
52 52
53-p:: 53-p::
54--pid=:: 54--pid=::
55 Record events on existing process ID. 55 Record events on existing process ID (comma separated list).
56 56
57-t:: 57-t::
58--tid=:: 58--tid=::
59 Record events on existing thread ID. 59 Record events on existing thread ID (comma separated list).
60
61-u::
62--uid=::
63 Record events in threads owned by uid. Name or number.
60 64
61-r:: 65-r::
62--realtime=:: 66--realtime=::
diff --git a/tools/perf/Documentation/perf-script.txt b/tools/perf/Documentation/perf-script.txt
index 2f6cef43da25..e9cbfcddfa3f 100644
--- a/tools/perf/Documentation/perf-script.txt
+++ b/tools/perf/Documentation/perf-script.txt
@@ -115,7 +115,7 @@ OPTIONS
115-f:: 115-f::
116--fields:: 116--fields::
117 Comma separated list of fields to print. Options are: 117 Comma separated list of fields to print. Options are:
118 comm, tid, pid, time, cpu, event, trace, ip, sym, dso, addr. 118 comm, tid, pid, time, cpu, event, trace, ip, sym, dso, addr, symoff.
119 Field list can be prepended with the type, trace, sw or hw, 119 Field list can be prepended with the type, trace, sw or hw,
120 to indicate to which event type the field list applies. 120 to indicate to which event type the field list applies.
121 e.g., -f sw:comm,tid,time,ip,sym and -f trace:time,cpu,trace 121 e.g., -f sw:comm,tid,time,ip,sym and -f trace:time,cpu,trace
@@ -200,6 +200,9 @@ OPTIONS
200 It currently includes: cpu and numa topology of the host system. 200 It currently includes: cpu and numa topology of the host system.
201 It can only be used with the perf script report mode. 201 It can only be used with the perf script report mode.
202 202
203--show-kernel-path::
204 Try to resolve the path of [kernel.kallsyms]
205
203SEE ALSO 206SEE ALSO
204-------- 207--------
205linkperf:perf-record[1], linkperf:perf-script-perl[1], 208linkperf:perf-record[1], linkperf:perf-script-perl[1],
diff --git a/tools/perf/Documentation/perf-stat.txt b/tools/perf/Documentation/perf-stat.txt
index 8966b9ab2014..2fa173b51970 100644
--- a/tools/perf/Documentation/perf-stat.txt
+++ b/tools/perf/Documentation/perf-stat.txt
@@ -35,11 +35,11 @@ OPTIONS
35 child tasks do not inherit counters 35 child tasks do not inherit counters
36-p:: 36-p::
37--pid=<pid>:: 37--pid=<pid>::
38 stat events on existing process id 38 stat events on existing process id (comma separated list)
39 39
40-t:: 40-t::
41--tid=<tid>:: 41--tid=<tid>::
42 stat events on existing thread id 42 stat events on existing thread id (comma separated list)
43 43
44 44
45-a:: 45-a::
diff --git a/tools/perf/Documentation/perf-top.txt b/tools/perf/Documentation/perf-top.txt
index b1a5bbbfebef..4a5680cb242e 100644
--- a/tools/perf/Documentation/perf-top.txt
+++ b/tools/perf/Documentation/perf-top.txt
@@ -72,11 +72,15 @@ Default is to monitor all CPUS.
72 72
73-p <pid>:: 73-p <pid>::
74--pid=<pid>:: 74--pid=<pid>::
75 Profile events on existing Process ID. 75 Profile events on existing Process ID (comma separated list).
76 76
77-t <tid>:: 77-t <tid>::
78--tid=<tid>:: 78--tid=<tid>::
79 Profile events on existing thread ID. 79 Profile events on existing thread ID (comma separated list).
80
81-u::
82--uid=::
83 Record events in threads owned by uid. Name or number.
80 84
81-r <priority>:: 85-r <priority>::
82--realtime=<priority>:: 86--realtime=<priority>::
diff --git a/tools/perf/MANIFEST b/tools/perf/MANIFEST
index 1078c5fadd5b..5476bc0a1eac 100644
--- a/tools/perf/MANIFEST
+++ b/tools/perf/MANIFEST
@@ -9,6 +9,7 @@ lib/rbtree.c
9include/linux/swab.h 9include/linux/swab.h
10arch/*/include/asm/unistd*.h 10arch/*/include/asm/unistd*.h
11arch/*/lib/memcpy*.S 11arch/*/lib/memcpy*.S
12arch/*/lib/memset*.S
12include/linux/poison.h 13include/linux/poison.h
13include/linux/magic.h 14include/linux/magic.h
14include/linux/hw_breakpoint.h 15include/linux/hw_breakpoint.h
diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index 7c12650165ae..e011b5060f92 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -61,7 +61,7 @@ ifeq ($(ARCH),x86_64)
61 ifeq (${IS_X86_64}, 1) 61 ifeq (${IS_X86_64}, 1)
62 RAW_ARCH := x86_64 62 RAW_ARCH := x86_64
63 ARCH_CFLAGS := -DARCH_X86_64 63 ARCH_CFLAGS := -DARCH_X86_64
64 ARCH_INCLUDE = ../../arch/x86/lib/memcpy_64.S 64 ARCH_INCLUDE = ../../arch/x86/lib/memcpy_64.S ../../arch/x86/lib/memset_64.S
65 endif 65 endif
66endif 66endif
67 67
@@ -183,7 +183,10 @@ SCRIPT_SH += perf-archive.sh
183grep-libs = $(filter -l%,$(1)) 183grep-libs = $(filter -l%,$(1))
184strip-libs = $(filter-out -l%,$(1)) 184strip-libs = $(filter-out -l%,$(1))
185 185
186$(OUTPUT)python/perf.so: $(PYRF_OBJS) 186PYTHON_EXT_SRCS := $(shell grep -v ^\# util/python-ext-sources)
187PYTHON_EXT_DEPS := util/python-ext-sources util/setup.py
188
189$(OUTPUT)python/perf.so: $(PYRF_OBJS) $(PYTHON_EXT_SRCS) $(PYTHON_EXT_DEPS)
187 $(QUIET_GEN)CFLAGS='$(BASIC_CFLAGS)' $(PYTHON_WORD) util/setup.py \ 190 $(QUIET_GEN)CFLAGS='$(BASIC_CFLAGS)' $(PYTHON_WORD) util/setup.py \
188 --quiet build_ext; \ 191 --quiet build_ext; \
189 mkdir -p $(OUTPUT)python && \ 192 mkdir -p $(OUTPUT)python && \
@@ -256,6 +259,7 @@ LIB_H += util/callchain.h
256LIB_H += util/build-id.h 259LIB_H += util/build-id.h
257LIB_H += util/debug.h 260LIB_H += util/debug.h
258LIB_H += util/debugfs.h 261LIB_H += util/debugfs.h
262LIB_H += util/sysfs.h
259LIB_H += util/event.h 263LIB_H += util/event.h
260LIB_H += util/evsel.h 264LIB_H += util/evsel.h
261LIB_H += util/evlist.h 265LIB_H += util/evlist.h
@@ -302,6 +306,7 @@ LIB_OBJS += $(OUTPUT)util/build-id.o
302LIB_OBJS += $(OUTPUT)util/config.o 306LIB_OBJS += $(OUTPUT)util/config.o
303LIB_OBJS += $(OUTPUT)util/ctype.o 307LIB_OBJS += $(OUTPUT)util/ctype.o
304LIB_OBJS += $(OUTPUT)util/debugfs.o 308LIB_OBJS += $(OUTPUT)util/debugfs.o
309LIB_OBJS += $(OUTPUT)util/sysfs.o
305LIB_OBJS += $(OUTPUT)util/environment.o 310LIB_OBJS += $(OUTPUT)util/environment.o
306LIB_OBJS += $(OUTPUT)util/event.o 311LIB_OBJS += $(OUTPUT)util/event.o
307LIB_OBJS += $(OUTPUT)util/evlist.o 312LIB_OBJS += $(OUTPUT)util/evlist.o
@@ -359,8 +364,10 @@ BUILTIN_OBJS += $(OUTPUT)bench/sched-messaging.o
359BUILTIN_OBJS += $(OUTPUT)bench/sched-pipe.o 364BUILTIN_OBJS += $(OUTPUT)bench/sched-pipe.o
360ifeq ($(RAW_ARCH),x86_64) 365ifeq ($(RAW_ARCH),x86_64)
361BUILTIN_OBJS += $(OUTPUT)bench/mem-memcpy-x86-64-asm.o 366BUILTIN_OBJS += $(OUTPUT)bench/mem-memcpy-x86-64-asm.o
367BUILTIN_OBJS += $(OUTPUT)bench/mem-memset-x86-64-asm.o
362endif 368endif
363BUILTIN_OBJS += $(OUTPUT)bench/mem-memcpy.o 369BUILTIN_OBJS += $(OUTPUT)bench/mem-memcpy.o
370BUILTIN_OBJS += $(OUTPUT)bench/mem-memset.o
364 371
365BUILTIN_OBJS += $(OUTPUT)builtin-diff.o 372BUILTIN_OBJS += $(OUTPUT)builtin-diff.o
366BUILTIN_OBJS += $(OUTPUT)builtin-evlist.o 373BUILTIN_OBJS += $(OUTPUT)builtin-evlist.o
@@ -792,7 +799,6 @@ help:
792 @echo ' quick-install-html - install the html documentation quickly' 799 @echo ' quick-install-html - install the html documentation quickly'
793 @echo '' 800 @echo ''
794 @echo 'Perf maintainer targets:' 801 @echo 'Perf maintainer targets:'
795 @echo ' distclean - alias to clean'
796 @echo ' clean - clean all binary objects and build output' 802 @echo ' clean - clean all binary objects and build output'
797 803
798doc: 804doc:
diff --git a/tools/perf/bench/bench.h b/tools/perf/bench/bench.h
index f7781c6267c0..a09bece6dad2 100644
--- a/tools/perf/bench/bench.h
+++ b/tools/perf/bench/bench.h
@@ -4,6 +4,7 @@
4extern int bench_sched_messaging(int argc, const char **argv, const char *prefix); 4extern int bench_sched_messaging(int argc, const char **argv, const char *prefix);
5extern int bench_sched_pipe(int argc, const char **argv, const char *prefix); 5extern int bench_sched_pipe(int argc, const char **argv, const char *prefix);
6extern int bench_mem_memcpy(int argc, const char **argv, const char *prefix __used); 6extern int bench_mem_memcpy(int argc, const char **argv, const char *prefix __used);
7extern int bench_mem_memset(int argc, const char **argv, const char *prefix);
7 8
8#define BENCH_FORMAT_DEFAULT_STR "default" 9#define BENCH_FORMAT_DEFAULT_STR "default"
9#define BENCH_FORMAT_DEFAULT 0 10#define BENCH_FORMAT_DEFAULT 0
diff --git a/tools/perf/bench/mem-memcpy-x86-64-asm-def.h b/tools/perf/bench/mem-memcpy-x86-64-asm-def.h
index d588b87696fc..d66ab799b35f 100644
--- a/tools/perf/bench/mem-memcpy-x86-64-asm-def.h
+++ b/tools/perf/bench/mem-memcpy-x86-64-asm-def.h
@@ -2,3 +2,11 @@
2MEMCPY_FN(__memcpy, 2MEMCPY_FN(__memcpy,
3 "x86-64-unrolled", 3 "x86-64-unrolled",
4 "unrolled memcpy() in arch/x86/lib/memcpy_64.S") 4 "unrolled memcpy() in arch/x86/lib/memcpy_64.S")
5
6MEMCPY_FN(memcpy_c,
7 "x86-64-movsq",
8 "movsq-based memcpy() in arch/x86/lib/memcpy_64.S")
9
10MEMCPY_FN(memcpy_c_e,
11 "x86-64-movsb",
12 "movsb-based memcpy() in arch/x86/lib/memcpy_64.S")
diff --git a/tools/perf/bench/mem-memcpy-x86-64-asm.S b/tools/perf/bench/mem-memcpy-x86-64-asm.S
index 185a96d66dd1..fcd9cf00600a 100644
--- a/tools/perf/bench/mem-memcpy-x86-64-asm.S
+++ b/tools/perf/bench/mem-memcpy-x86-64-asm.S
@@ -1,4 +1,8 @@
1 1#define memcpy MEMCPY /* don't hide glibc's memcpy() */
2#define altinstr_replacement text
3#define globl p2align 4; .globl
4#define Lmemcpy_c globl memcpy_c; memcpy_c
5#define Lmemcpy_c_e globl memcpy_c_e; memcpy_c_e
2#include "../../../arch/x86/lib/memcpy_64.S" 6#include "../../../arch/x86/lib/memcpy_64.S"
3/* 7/*
4 * We need to provide note.GNU-stack section, saying that we want 8 * We need to provide note.GNU-stack section, saying that we want
diff --git a/tools/perf/bench/mem-memcpy.c b/tools/perf/bench/mem-memcpy.c
index db82021f4b91..71557225bf92 100644
--- a/tools/perf/bench/mem-memcpy.c
+++ b/tools/perf/bench/mem-memcpy.c
@@ -5,7 +5,6 @@
5 * 5 *
6 * Written by Hitoshi Mitake <mitake@dcl.info.waseda.ac.jp> 6 * Written by Hitoshi Mitake <mitake@dcl.info.waseda.ac.jp>
7 */ 7 */
8#include <ctype.h>
9 8
10#include "../perf.h" 9#include "../perf.h"
11#include "../util/util.h" 10#include "../util/util.h"
@@ -24,6 +23,7 @@
24 23
25static const char *length_str = "1MB"; 24static const char *length_str = "1MB";
26static const char *routine = "default"; 25static const char *routine = "default";
26static int iterations = 1;
27static bool use_clock; 27static bool use_clock;
28static int clock_fd; 28static int clock_fd;
29static bool only_prefault; 29static bool only_prefault;
@@ -35,6 +35,8 @@ static const struct option options[] = {
35 "available unit: B, MB, GB (upper and lower)"), 35 "available unit: B, MB, GB (upper and lower)"),
36 OPT_STRING('r', "routine", &routine, "default", 36 OPT_STRING('r', "routine", &routine, "default",
37 "Specify routine to copy"), 37 "Specify routine to copy"),
38 OPT_INTEGER('i', "iterations", &iterations,
39 "repeat memcpy() invocation this number of times"),
38 OPT_BOOLEAN('c', "clock", &use_clock, 40 OPT_BOOLEAN('c', "clock", &use_clock,
39 "Use CPU clock for measuring"), 41 "Use CPU clock for measuring"),
40 OPT_BOOLEAN('o', "only-prefault", &only_prefault, 42 OPT_BOOLEAN('o', "only-prefault", &only_prefault,
@@ -121,6 +123,7 @@ static u64 do_memcpy_clock(memcpy_t fn, size_t len, bool prefault)
121{ 123{
122 u64 clock_start = 0ULL, clock_end = 0ULL; 124 u64 clock_start = 0ULL, clock_end = 0ULL;
123 void *src = NULL, *dst = NULL; 125 void *src = NULL, *dst = NULL;
126 int i;
124 127
125 alloc_mem(&src, &dst, len); 128 alloc_mem(&src, &dst, len);
126 129
@@ -128,7 +131,8 @@ static u64 do_memcpy_clock(memcpy_t fn, size_t len, bool prefault)
128 fn(dst, src, len); 131 fn(dst, src, len);
129 132
130 clock_start = get_clock(); 133 clock_start = get_clock();
131 fn(dst, src, len); 134 for (i = 0; i < iterations; ++i)
135 fn(dst, src, len);
132 clock_end = get_clock(); 136 clock_end = get_clock();
133 137
134 free(src); 138 free(src);
@@ -140,6 +144,7 @@ static double do_memcpy_gettimeofday(memcpy_t fn, size_t len, bool prefault)
140{ 144{
141 struct timeval tv_start, tv_end, tv_diff; 145 struct timeval tv_start, tv_end, tv_diff;
142 void *src = NULL, *dst = NULL; 146 void *src = NULL, *dst = NULL;
147 int i;
143 148
144 alloc_mem(&src, &dst, len); 149 alloc_mem(&src, &dst, len);
145 150
@@ -147,7 +152,8 @@ static double do_memcpy_gettimeofday(memcpy_t fn, size_t len, bool prefault)
147 fn(dst, src, len); 152 fn(dst, src, len);
148 153
149 BUG_ON(gettimeofday(&tv_start, NULL)); 154 BUG_ON(gettimeofday(&tv_start, NULL));
150 fn(dst, src, len); 155 for (i = 0; i < iterations; ++i)
156 fn(dst, src, len);
151 BUG_ON(gettimeofday(&tv_end, NULL)); 157 BUG_ON(gettimeofday(&tv_end, NULL));
152 158
153 timersub(&tv_end, &tv_start, &tv_diff); 159 timersub(&tv_end, &tv_start, &tv_diff);
diff --git a/tools/perf/bench/mem-memset-arch.h b/tools/perf/bench/mem-memset-arch.h
new file mode 100644
index 000000000000..a040fa77665b
--- /dev/null
+++ b/tools/perf/bench/mem-memset-arch.h
@@ -0,0 +1,12 @@
1
2#ifdef ARCH_X86_64
3
4#define MEMSET_FN(fn, name, desc) \
5 extern void *fn(void *, int, size_t);
6
7#include "mem-memset-x86-64-asm-def.h"
8
9#undef MEMSET_FN
10
11#endif
12
diff --git a/tools/perf/bench/mem-memset-x86-64-asm-def.h b/tools/perf/bench/mem-memset-x86-64-asm-def.h
new file mode 100644
index 000000000000..a71dff97c1f5
--- /dev/null
+++ b/tools/perf/bench/mem-memset-x86-64-asm-def.h
@@ -0,0 +1,12 @@
1
2MEMSET_FN(__memset,
3 "x86-64-unrolled",
4 "unrolled memset() in arch/x86/lib/memset_64.S")
5
6MEMSET_FN(memset_c,
7 "x86-64-stosq",
8 "movsq-based memset() in arch/x86/lib/memset_64.S")
9
10MEMSET_FN(memset_c_e,
11 "x86-64-stosb",
12 "movsb-based memset() in arch/x86/lib/memset_64.S")
diff --git a/tools/perf/bench/mem-memset-x86-64-asm.S b/tools/perf/bench/mem-memset-x86-64-asm.S
new file mode 100644
index 000000000000..9e5af89ed13a
--- /dev/null
+++ b/tools/perf/bench/mem-memset-x86-64-asm.S
@@ -0,0 +1,13 @@
1#define memset MEMSET /* don't hide glibc's memset() */
2#define altinstr_replacement text
3#define globl p2align 4; .globl
4#define Lmemset_c globl memset_c; memset_c
5#define Lmemset_c_e globl memset_c_e; memset_c_e
6#include "../../../arch/x86/lib/memset_64.S"
7
8/*
9 * We need to provide note.GNU-stack section, saying that we want
10 * NOT executable stack. Otherwise the final linking will assume that
11 * the ELF stack should not be restricted at all and set it RWX.
12 */
13.section .note.GNU-stack,"",@progbits
diff --git a/tools/perf/bench/mem-memset.c b/tools/perf/bench/mem-memset.c
new file mode 100644
index 000000000000..e9079185bd72
--- /dev/null
+++ b/tools/perf/bench/mem-memset.c
@@ -0,0 +1,297 @@
1/*
2 * mem-memset.c
3 *
4 * memset: Simple memory set in various ways
5 *
6 * Trivial clone of mem-memcpy.c.
7 */
8
9#include "../perf.h"
10#include "../util/util.h"
11#include "../util/parse-options.h"
12#include "../util/header.h"
13#include "bench.h"
14#include "mem-memset-arch.h"
15
16#include <stdio.h>
17#include <stdlib.h>
18#include <string.h>
19#include <sys/time.h>
20#include <errno.h>
21
22#define K 1024
23
24static const char *length_str = "1MB";
25static const char *routine = "default";
26static int iterations = 1;
27static bool use_clock;
28static int clock_fd;
29static bool only_prefault;
30static bool no_prefault;
31
32static const struct option options[] = {
33 OPT_STRING('l', "length", &length_str, "1MB",
34 "Specify length of memory to copy. "
35 "available unit: B, MB, GB (upper and lower)"),
36 OPT_STRING('r', "routine", &routine, "default",
37 "Specify routine to copy"),
38 OPT_INTEGER('i', "iterations", &iterations,
39 "repeat memset() invocation this number of times"),
40 OPT_BOOLEAN('c', "clock", &use_clock,
41 "Use CPU clock for measuring"),
42 OPT_BOOLEAN('o', "only-prefault", &only_prefault,
43 "Show only the result with page faults before memset()"),
44 OPT_BOOLEAN('n', "no-prefault", &no_prefault,
45 "Show only the result without page faults before memset()"),
46 OPT_END()
47};
48
49typedef void *(*memset_t)(void *, int, size_t);
50
51struct routine {
52 const char *name;
53 const char *desc;
54 memset_t fn;
55};
56
57static const struct routine routines[] = {
58 { "default",
59 "Default memset() provided by glibc",
60 memset },
61#ifdef ARCH_X86_64
62
63#define MEMSET_FN(fn, name, desc) { name, desc, fn },
64#include "mem-memset-x86-64-asm-def.h"
65#undef MEMSET_FN
66
67#endif
68
69 { NULL,
70 NULL,
71 NULL }
72};
73
74static const char * const bench_mem_memset_usage[] = {
75 "perf bench mem memset <options>",
76 NULL
77};
78
79static struct perf_event_attr clock_attr = {
80 .type = PERF_TYPE_HARDWARE,
81 .config = PERF_COUNT_HW_CPU_CYCLES
82};
83
84static void init_clock(void)
85{
86 clock_fd = sys_perf_event_open(&clock_attr, getpid(), -1, -1, 0);
87
88 if (clock_fd < 0 && errno == ENOSYS)
89 die("No CONFIG_PERF_EVENTS=y kernel support configured?\n");
90 else
91 BUG_ON(clock_fd < 0);
92}
93
94static u64 get_clock(void)
95{
96 int ret;
97 u64 clk;
98
99 ret = read(clock_fd, &clk, sizeof(u64));
100 BUG_ON(ret != sizeof(u64));
101
102 return clk;
103}
104
105static double timeval2double(struct timeval *ts)
106{
107 return (double)ts->tv_sec +
108 (double)ts->tv_usec / (double)1000000;
109}
110
111static void alloc_mem(void **dst, size_t length)
112{
113 *dst = zalloc(length);
114 if (!dst)
115 die("memory allocation failed - maybe length is too large?\n");
116}
117
118static u64 do_memset_clock(memset_t fn, size_t len, bool prefault)
119{
120 u64 clock_start = 0ULL, clock_end = 0ULL;
121 void *dst = NULL;
122 int i;
123
124 alloc_mem(&dst, len);
125
126 if (prefault)
127 fn(dst, -1, len);
128
129 clock_start = get_clock();
130 for (i = 0; i < iterations; ++i)
131 fn(dst, i, len);
132 clock_end = get_clock();
133
134 free(dst);
135 return clock_end - clock_start;
136}
137
138static double do_memset_gettimeofday(memset_t fn, size_t len, bool prefault)
139{
140 struct timeval tv_start, tv_end, tv_diff;
141 void *dst = NULL;
142 int i;
143
144 alloc_mem(&dst, len);
145
146 if (prefault)
147 fn(dst, -1, len);
148
149 BUG_ON(gettimeofday(&tv_start, NULL));
150 for (i = 0; i < iterations; ++i)
151 fn(dst, i, len);
152 BUG_ON(gettimeofday(&tv_end, NULL));
153
154 timersub(&tv_end, &tv_start, &tv_diff);
155
156 free(dst);
157 return (double)((double)len / timeval2double(&tv_diff));
158}
159
160#define pf (no_prefault ? 0 : 1)
161
162#define print_bps(x) do { \
163 if (x < K) \
164 printf(" %14lf B/Sec", x); \
165 else if (x < K * K) \
166 printf(" %14lfd KB/Sec", x / K); \
167 else if (x < K * K * K) \
168 printf(" %14lf MB/Sec", x / K / K); \
169 else \
170 printf(" %14lf GB/Sec", x / K / K / K); \
171 } while (0)
172
173int bench_mem_memset(int argc, const char **argv,
174 const char *prefix __used)
175{
176 int i;
177 size_t len;
178 double result_bps[2];
179 u64 result_clock[2];
180
181 argc = parse_options(argc, argv, options,
182 bench_mem_memset_usage, 0);
183
184 if (use_clock)
185 init_clock();
186
187 len = (size_t)perf_atoll((char *)length_str);
188
189 result_clock[0] = result_clock[1] = 0ULL;
190 result_bps[0] = result_bps[1] = 0.0;
191
192 if ((s64)len <= 0) {
193 fprintf(stderr, "Invalid length:%s\n", length_str);
194 return 1;
195 }
196
197 /* same to without specifying either of prefault and no-prefault */
198 if (only_prefault && no_prefault)
199 only_prefault = no_prefault = false;
200
201 for (i = 0; routines[i].name; i++) {
202 if (!strcmp(routines[i].name, routine))
203 break;
204 }
205 if (!routines[i].name) {
206 printf("Unknown routine:%s\n", routine);
207 printf("Available routines...\n");
208 for (i = 0; routines[i].name; i++) {
209 printf("\t%s ... %s\n",
210 routines[i].name, routines[i].desc);
211 }
212 return 1;
213 }
214
215 if (bench_format == BENCH_FORMAT_DEFAULT)
216 printf("# Copying %s Bytes ...\n\n", length_str);
217
218 if (!only_prefault && !no_prefault) {
219 /* show both of results */
220 if (use_clock) {
221 result_clock[0] =
222 do_memset_clock(routines[i].fn, len, false);
223 result_clock[1] =
224 do_memset_clock(routines[i].fn, len, true);
225 } else {
226 result_bps[0] =
227 do_memset_gettimeofday(routines[i].fn,
228 len, false);
229 result_bps[1] =
230 do_memset_gettimeofday(routines[i].fn,
231 len, true);
232 }
233 } else {
234 if (use_clock) {
235 result_clock[pf] =
236 do_memset_clock(routines[i].fn,
237 len, only_prefault);
238 } else {
239 result_bps[pf] =
240 do_memset_gettimeofday(routines[i].fn,
241 len, only_prefault);
242 }
243 }
244
245 switch (bench_format) {
246 case BENCH_FORMAT_DEFAULT:
247 if (!only_prefault && !no_prefault) {
248 if (use_clock) {
249 printf(" %14lf Clock/Byte\n",
250 (double)result_clock[0]
251 / (double)len);
252 printf(" %14lf Clock/Byte (with prefault)\n ",
253 (double)result_clock[1]
254 / (double)len);
255 } else {
256 print_bps(result_bps[0]);
257 printf("\n");
258 print_bps(result_bps[1]);
259 printf(" (with prefault)\n");
260 }
261 } else {
262 if (use_clock) {
263 printf(" %14lf Clock/Byte",
264 (double)result_clock[pf]
265 / (double)len);
266 } else
267 print_bps(result_bps[pf]);
268
269 printf("%s\n", only_prefault ? " (with prefault)" : "");
270 }
271 break;
272 case BENCH_FORMAT_SIMPLE:
273 if (!only_prefault && !no_prefault) {
274 if (use_clock) {
275 printf("%lf %lf\n",
276 (double)result_clock[0] / (double)len,
277 (double)result_clock[1] / (double)len);
278 } else {
279 printf("%lf %lf\n",
280 result_bps[0], result_bps[1]);
281 }
282 } else {
283 if (use_clock) {
284 printf("%lf\n", (double)result_clock[pf]
285 / (double)len);
286 } else
287 printf("%lf\n", result_bps[pf]);
288 }
289 break;
290 default:
291 /* reaching this means there's some disaster: */
292 die("unknown format: %d\n", bench_format);
293 break;
294 }
295
296 return 0;
297}
diff --git a/tools/perf/builtin-bench.c b/tools/perf/builtin-bench.c
index fcb96269852a..b0e74ab2d7a2 100644
--- a/tools/perf/builtin-bench.c
+++ b/tools/perf/builtin-bench.c
@@ -52,6 +52,9 @@ static struct bench_suite mem_suites[] = {
52 { "memcpy", 52 { "memcpy",
53 "Simple memory copy in various ways", 53 "Simple memory copy in various ways",
54 bench_mem_memcpy }, 54 bench_mem_memcpy },
55 { "memset",
56 "Simple memory set in various ways",
57 bench_mem_memset },
55 suite_all, 58 suite_all,
56 { NULL, 59 { NULL,
57 NULL, 60 NULL,
diff --git a/tools/perf/builtin-lock.c b/tools/perf/builtin-lock.c
index 2296c391d0f5..12c814838993 100644
--- a/tools/perf/builtin-lock.c
+++ b/tools/perf/builtin-lock.c
@@ -922,12 +922,12 @@ static const struct option info_options[] = {
922 OPT_BOOLEAN('t', "threads", &info_threads, 922 OPT_BOOLEAN('t', "threads", &info_threads,
923 "dump thread list in perf.data"), 923 "dump thread list in perf.data"),
924 OPT_BOOLEAN('m', "map", &info_map, 924 OPT_BOOLEAN('m', "map", &info_map,
925 "map of lock instances (name:address table)"), 925 "map of lock instances (address:name table)"),
926 OPT_END() 926 OPT_END()
927}; 927};
928 928
929static const char * const lock_usage[] = { 929static const char * const lock_usage[] = {
930 "perf lock [<options>] {record|trace|report}", 930 "perf lock [<options>] {record|report|script|info}",
931 NULL 931 NULL
932}; 932};
933 933
diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c
index fb8566181f27..4935c09dd5b5 100644
--- a/tools/perf/builtin-probe.c
+++ b/tools/perf/builtin-probe.c
@@ -58,7 +58,7 @@ static struct {
58 struct perf_probe_event events[MAX_PROBES]; 58 struct perf_probe_event events[MAX_PROBES];
59 struct strlist *dellist; 59 struct strlist *dellist;
60 struct line_range line_range; 60 struct line_range line_range;
61 const char *target_module; 61 const char *target;
62 int max_probe_points; 62 int max_probe_points;
63 struct strfilter *filter; 63 struct strfilter *filter;
64} params; 64} params;
@@ -246,7 +246,7 @@ static const struct option options[] = {
246 "file", "vmlinux pathname"), 246 "file", "vmlinux pathname"),
247 OPT_STRING('s', "source", &symbol_conf.source_prefix, 247 OPT_STRING('s', "source", &symbol_conf.source_prefix,
248 "directory", "path to kernel source"), 248 "directory", "path to kernel source"),
249 OPT_STRING('m', "module", &params.target_module, 249 OPT_STRING('m', "module", &params.target,
250 "modname|path", 250 "modname|path",
251 "target module name (for online) or path (for offline)"), 251 "target module name (for online) or path (for offline)"),
252#endif 252#endif
@@ -333,7 +333,7 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used)
333 if (!params.filter) 333 if (!params.filter)
334 params.filter = strfilter__new(DEFAULT_FUNC_FILTER, 334 params.filter = strfilter__new(DEFAULT_FUNC_FILTER,
335 NULL); 335 NULL);
336 ret = show_available_funcs(params.target_module, 336 ret = show_available_funcs(params.target,
337 params.filter); 337 params.filter);
338 strfilter__delete(params.filter); 338 strfilter__delete(params.filter);
339 if (ret < 0) 339 if (ret < 0)
@@ -354,7 +354,7 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used)
354 usage_with_options(probe_usage, options); 354 usage_with_options(probe_usage, options);
355 } 355 }
356 356
357 ret = show_line_range(&params.line_range, params.target_module); 357 ret = show_line_range(&params.line_range, params.target);
358 if (ret < 0) 358 if (ret < 0)
359 pr_err(" Error: Failed to show lines. (%d)\n", ret); 359 pr_err(" Error: Failed to show lines. (%d)\n", ret);
360 return ret; 360 return ret;
@@ -371,7 +371,7 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used)
371 371
372 ret = show_available_vars(params.events, params.nevents, 372 ret = show_available_vars(params.events, params.nevents,
373 params.max_probe_points, 373 params.max_probe_points,
374 params.target_module, 374 params.target,
375 params.filter, 375 params.filter,
376 params.show_ext_vars); 376 params.show_ext_vars);
377 strfilter__delete(params.filter); 377 strfilter__delete(params.filter);
@@ -393,7 +393,7 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used)
393 if (params.nevents) { 393 if (params.nevents) {
394 ret = add_perf_probe_events(params.events, params.nevents, 394 ret = add_perf_probe_events(params.events, params.nevents,
395 params.max_probe_points, 395 params.max_probe_points,
396 params.target_module, 396 params.target,
397 params.force_add); 397 params.force_add);
398 if (ret < 0) { 398 if (ret < 0) {
399 pr_err(" Error: Failed to add events. (%d)\n", ret); 399 pr_err(" Error: Failed to add events. (%d)\n", ret);
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 227b6ae99785..75d230fef202 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -44,6 +44,7 @@ struct perf_record {
44 struct perf_evlist *evlist; 44 struct perf_evlist *evlist;
45 struct perf_session *session; 45 struct perf_session *session;
46 const char *progname; 46 const char *progname;
47 const char *uid_str;
47 int output; 48 int output;
48 unsigned int page_size; 49 unsigned int page_size;
49 int realtime_prio; 50 int realtime_prio;
@@ -208,7 +209,7 @@ fallback_missing_features:
208 if (opts->exclude_guest_missing) 209 if (opts->exclude_guest_missing)
209 attr->exclude_guest = attr->exclude_host = 0; 210 attr->exclude_guest = attr->exclude_host = 0;
210retry_sample_id: 211retry_sample_id:
211 attr->sample_id_all = opts->sample_id_all_avail ? 1 : 0; 212 attr->sample_id_all = opts->sample_id_all_missing ? 0 : 1;
212try_again: 213try_again:
213 if (perf_evsel__open(pos, evlist->cpus, evlist->threads, 214 if (perf_evsel__open(pos, evlist->cpus, evlist->threads,
214 opts->group, group_fd) < 0) { 215 opts->group, group_fd) < 0) {
@@ -227,11 +228,11 @@ try_again:
227 "guest or host samples.\n"); 228 "guest or host samples.\n");
228 opts->exclude_guest_missing = true; 229 opts->exclude_guest_missing = true;
229 goto fallback_missing_features; 230 goto fallback_missing_features;
230 } else if (opts->sample_id_all_avail) { 231 } else if (!opts->sample_id_all_missing) {
231 /* 232 /*
232 * Old kernel, no attr->sample_id_type_all field 233 * Old kernel, no attr->sample_id_type_all field
233 */ 234 */
234 opts->sample_id_all_avail = false; 235 opts->sample_id_all_missing = true;
235 if (!opts->sample_time && !opts->raw_samples && !time_needed) 236 if (!opts->sample_time && !opts->raw_samples && !time_needed)
236 attr->sample_type &= ~PERF_SAMPLE_TIME; 237 attr->sample_type &= ~PERF_SAMPLE_TIME;
237 238
@@ -396,7 +397,7 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
396{ 397{
397 struct stat st; 398 struct stat st;
398 int flags; 399 int flags;
399 int err, output; 400 int err, output, feat;
400 unsigned long waking = 0; 401 unsigned long waking = 0;
401 const bool forks = argc > 0; 402 const bool forks = argc > 0;
402 struct machine *machine; 403 struct machine *machine;
@@ -463,8 +464,14 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
463 464
464 rec->session = session; 465 rec->session = session;
465 466
466 if (!rec->no_buildid) 467 for (feat = HEADER_FIRST_FEATURE; feat < HEADER_LAST_FEATURE; feat++)
467 perf_header__set_feat(&session->header, HEADER_BUILD_ID); 468 perf_header__set_feat(&session->header, feat);
469
470 if (rec->no_buildid)
471 perf_header__clear_feat(&session->header, HEADER_BUILD_ID);
472
473 if (!have_tracepoints(&evsel_list->entries))
474 perf_header__clear_feat(&session->header, HEADER_TRACE_INFO);
468 475
469 if (!rec->file_new) { 476 if (!rec->file_new) {
470 err = perf_session__read_header(session, output); 477 err = perf_session__read_header(session, output);
@@ -472,22 +479,6 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
472 goto out_delete_session; 479 goto out_delete_session;
473 } 480 }
474 481
475 if (have_tracepoints(&evsel_list->entries))
476 perf_header__set_feat(&session->header, HEADER_TRACE_INFO);
477
478 perf_header__set_feat(&session->header, HEADER_HOSTNAME);
479 perf_header__set_feat(&session->header, HEADER_OSRELEASE);
480 perf_header__set_feat(&session->header, HEADER_ARCH);
481 perf_header__set_feat(&session->header, HEADER_CPUDESC);
482 perf_header__set_feat(&session->header, HEADER_NRCPUS);
483 perf_header__set_feat(&session->header, HEADER_EVENT_DESC);
484 perf_header__set_feat(&session->header, HEADER_CMDLINE);
485 perf_header__set_feat(&session->header, HEADER_VERSION);
486 perf_header__set_feat(&session->header, HEADER_CPU_TOPOLOGY);
487 perf_header__set_feat(&session->header, HEADER_TOTAL_MEM);
488 perf_header__set_feat(&session->header, HEADER_NUMA_TOPOLOGY);
489 perf_header__set_feat(&session->header, HEADER_CPUID);
490
491 if (forks) { 482 if (forks) {
492 err = perf_evlist__prepare_workload(evsel_list, opts, argv); 483 err = perf_evlist__prepare_workload(evsel_list, opts, argv);
493 if (err < 0) { 484 if (err < 0) {
@@ -665,13 +656,10 @@ static const char * const record_usage[] = {
665 */ 656 */
666static struct perf_record record = { 657static struct perf_record record = {
667 .opts = { 658 .opts = {
668 .target_pid = -1,
669 .target_tid = -1,
670 .mmap_pages = UINT_MAX, 659 .mmap_pages = UINT_MAX,
671 .user_freq = UINT_MAX, 660 .user_freq = UINT_MAX,
672 .user_interval = ULLONG_MAX, 661 .user_interval = ULLONG_MAX,
673 .freq = 1000, 662 .freq = 1000,
674 .sample_id_all_avail = true,
675 }, 663 },
676 .write_mode = WRITE_FORCE, 664 .write_mode = WRITE_FORCE,
677 .file_new = true, 665 .file_new = true,
@@ -690,9 +678,9 @@ const struct option record_options[] = {
690 parse_events_option), 678 parse_events_option),
691 OPT_CALLBACK(0, "filter", &record.evlist, "filter", 679 OPT_CALLBACK(0, "filter", &record.evlist, "filter",
692 "event filter", parse_filter), 680 "event filter", parse_filter),
693 OPT_INTEGER('p', "pid", &record.opts.target_pid, 681 OPT_STRING('p', "pid", &record.opts.target_pid, "pid",
694 "record events on existing process id"), 682 "record events on existing process id"),
695 OPT_INTEGER('t', "tid", &record.opts.target_tid, 683 OPT_STRING('t', "tid", &record.opts.target_tid, "tid",
696 "record events on existing thread id"), 684 "record events on existing thread id"),
697 OPT_INTEGER('r', "realtime", &record.realtime_prio, 685 OPT_INTEGER('r', "realtime", &record.realtime_prio,
698 "collect data with this RT SCHED_FIFO priority"), 686 "collect data with this RT SCHED_FIFO priority"),
@@ -738,6 +726,7 @@ const struct option record_options[] = {
738 OPT_CALLBACK('G', "cgroup", &record.evlist, "name", 726 OPT_CALLBACK('G', "cgroup", &record.evlist, "name",
739 "monitor event in cgroup name only", 727 "monitor event in cgroup name only",
740 parse_cgroups), 728 parse_cgroups),
729 OPT_STRING('u', "uid", &record.uid_str, "user", "user to profile"),
741 OPT_END() 730 OPT_END()
742}; 731};
743 732
@@ -758,8 +747,8 @@ int cmd_record(int argc, const char **argv, const char *prefix __used)
758 747
759 argc = parse_options(argc, argv, record_options, record_usage, 748 argc = parse_options(argc, argv, record_options, record_usage,
760 PARSE_OPT_STOP_AT_NON_OPTION); 749 PARSE_OPT_STOP_AT_NON_OPTION);
761 if (!argc && rec->opts.target_pid == -1 && rec->opts.target_tid == -1 && 750 if (!argc && !rec->opts.target_pid && !rec->opts.target_tid &&
762 !rec->opts.system_wide && !rec->opts.cpu_list) 751 !rec->opts.system_wide && !rec->opts.cpu_list && !rec->uid_str)
763 usage_with_options(record_usage, record_options); 752 usage_with_options(record_usage, record_options);
764 753
765 if (rec->force && rec->append_file) { 754 if (rec->force && rec->append_file) {
@@ -799,11 +788,17 @@ int cmd_record(int argc, const char **argv, const char *prefix __used)
799 goto out_symbol_exit; 788 goto out_symbol_exit;
800 } 789 }
801 790
802 if (rec->opts.target_pid != -1) 791 rec->opts.uid = parse_target_uid(rec->uid_str, rec->opts.target_tid,
792 rec->opts.target_pid);
793 if (rec->uid_str != NULL && rec->opts.uid == UINT_MAX - 1)
794 goto out_free_fd;
795
796 if (rec->opts.target_pid)
803 rec->opts.target_tid = rec->opts.target_pid; 797 rec->opts.target_tid = rec->opts.target_pid;
804 798
805 if (perf_evlist__create_maps(evsel_list, rec->opts.target_pid, 799 if (perf_evlist__create_maps(evsel_list, rec->opts.target_pid,
806 rec->opts.target_tid, rec->opts.cpu_list) < 0) 800 rec->opts.target_tid, rec->opts.uid,
801 rec->opts.cpu_list) < 0)
807 usage_with_options(record_usage, record_options); 802 usage_with_options(record_usage, record_options);
808 803
809 list_for_each_entry(pos, &evsel_list->entries, node) { 804 list_for_each_entry(pos, &evsel_list->entries, node) {
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index bb68ddf257b7..d4ce733b9eba 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -40,6 +40,7 @@ enum perf_output_field {
40 PERF_OUTPUT_SYM = 1U << 8, 40 PERF_OUTPUT_SYM = 1U << 8,
41 PERF_OUTPUT_DSO = 1U << 9, 41 PERF_OUTPUT_DSO = 1U << 9,
42 PERF_OUTPUT_ADDR = 1U << 10, 42 PERF_OUTPUT_ADDR = 1U << 10,
43 PERF_OUTPUT_SYMOFFSET = 1U << 11,
43}; 44};
44 45
45struct output_option { 46struct output_option {
@@ -57,6 +58,7 @@ struct output_option {
57 {.str = "sym", .field = PERF_OUTPUT_SYM}, 58 {.str = "sym", .field = PERF_OUTPUT_SYM},
58 {.str = "dso", .field = PERF_OUTPUT_DSO}, 59 {.str = "dso", .field = PERF_OUTPUT_DSO},
59 {.str = "addr", .field = PERF_OUTPUT_ADDR}, 60 {.str = "addr", .field = PERF_OUTPUT_ADDR},
61 {.str = "symoff", .field = PERF_OUTPUT_SYMOFFSET},
60}; 62};
61 63
62/* default set to maintain compatibility with current format */ 64/* default set to maintain compatibility with current format */
@@ -193,6 +195,11 @@ static int perf_evsel__check_attr(struct perf_evsel *evsel,
193 "to symbols.\n"); 195 "to symbols.\n");
194 return -EINVAL; 196 return -EINVAL;
195 } 197 }
198 if (PRINT_FIELD(SYMOFFSET) && !PRINT_FIELD(SYM)) {
199 pr_err("Display of offsets requested but symbol is not"
200 "selected.\n");
201 return -EINVAL;
202 }
196 if (PRINT_FIELD(DSO) && !PRINT_FIELD(IP) && !PRINT_FIELD(ADDR)) { 203 if (PRINT_FIELD(DSO) && !PRINT_FIELD(IP) && !PRINT_FIELD(ADDR)) {
197 pr_err("Display of DSO requested but neither sample IP nor " 204 pr_err("Display of DSO requested but neither sample IP nor "
198 "sample address\nis selected. Hence, no addresses to convert " 205 "sample address\nis selected. Hence, no addresses to convert "
@@ -300,10 +307,17 @@ static void print_sample_start(struct perf_sample *sample,
300 } else 307 } else
301 evname = __event_name(attr->type, attr->config); 308 evname = __event_name(attr->type, attr->config);
302 309
303 printf("%s: ", evname ? evname : "(unknown)"); 310 printf("%s: ", evname ? evname : "[unknown]");
304 } 311 }
305} 312}
306 313
314static bool is_bts_event(struct perf_event_attr *attr)
315{
316 return ((attr->type == PERF_TYPE_HARDWARE) &&
317 (attr->config & PERF_COUNT_HW_BRANCH_INSTRUCTIONS) &&
318 (attr->sample_period == 1));
319}
320
307static bool sample_addr_correlates_sym(struct perf_event_attr *attr) 321static bool sample_addr_correlates_sym(struct perf_event_attr *attr)
308{ 322{
309 if ((attr->type == PERF_TYPE_SOFTWARE) && 323 if ((attr->type == PERF_TYPE_SOFTWARE) &&
@@ -312,6 +326,9 @@ static bool sample_addr_correlates_sym(struct perf_event_attr *attr)
312 (attr->config == PERF_COUNT_SW_PAGE_FAULTS_MAJ))) 326 (attr->config == PERF_COUNT_SW_PAGE_FAULTS_MAJ)))
313 return true; 327 return true;
314 328
329 if (is_bts_event(attr))
330 return true;
331
315 return false; 332 return false;
316} 333}
317 334
@@ -323,7 +340,6 @@ static void print_sample_addr(union perf_event *event,
323{ 340{
324 struct addr_location al; 341 struct addr_location al;
325 u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; 342 u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
326 const char *symname, *dsoname;
327 343
328 printf("%16" PRIx64, sample->addr); 344 printf("%16" PRIx64, sample->addr);
329 345
@@ -343,22 +359,46 @@ static void print_sample_addr(union perf_event *event,
343 al.sym = map__find_symbol(al.map, al.addr, NULL); 359 al.sym = map__find_symbol(al.map, al.addr, NULL);
344 360
345 if (PRINT_FIELD(SYM)) { 361 if (PRINT_FIELD(SYM)) {
346 if (al.sym && al.sym->name) 362 printf(" ");
347 symname = al.sym->name; 363 if (PRINT_FIELD(SYMOFFSET))
364 symbol__fprintf_symname_offs(al.sym, &al, stdout);
348 else 365 else
349 symname = ""; 366 symbol__fprintf_symname(al.sym, stdout);
350
351 printf(" %16s", symname);
352 } 367 }
353 368
354 if (PRINT_FIELD(DSO)) { 369 if (PRINT_FIELD(DSO)) {
355 if (al.map && al.map->dso && al.map->dso->name) 370 printf(" (");
356 dsoname = al.map->dso->name; 371 map__fprintf_dsoname(al.map, stdout);
357 else 372 printf(")");
358 dsoname = ""; 373 }
374}
359 375
360 printf(" (%s)", dsoname); 376static void print_sample_bts(union perf_event *event,
377 struct perf_sample *sample,
378 struct perf_evsel *evsel,
379 struct machine *machine,
380 struct thread *thread)
381{
382 struct perf_event_attr *attr = &evsel->attr;
383
384 /* print branch_from information */
385 if (PRINT_FIELD(IP)) {
386 if (!symbol_conf.use_callchain)
387 printf(" ");
388 else
389 printf("\n");
390 perf_event__print_ip(event, sample, machine, evsel,
391 PRINT_FIELD(SYM), PRINT_FIELD(DSO),
392 PRINT_FIELD(SYMOFFSET));
361 } 393 }
394
395 printf(" => ");
396
397 /* print branch_to information */
398 if (PRINT_FIELD(ADDR))
399 print_sample_addr(event, sample, machine, thread, attr);
400
401 printf("\n");
362} 402}
363 403
364static void process_event(union perf_event *event __unused, 404static void process_event(union perf_event *event __unused,
@@ -374,6 +414,11 @@ static void process_event(union perf_event *event __unused,
374 414
375 print_sample_start(sample, thread, attr); 415 print_sample_start(sample, thread, attr);
376 416
417 if (is_bts_event(attr)) {
418 print_sample_bts(event, sample, evsel, machine, thread);
419 return;
420 }
421
377 if (PRINT_FIELD(TRACE)) 422 if (PRINT_FIELD(TRACE))
378 print_trace_event(sample->cpu, sample->raw_data, 423 print_trace_event(sample->cpu, sample->raw_data,
379 sample->raw_size); 424 sample->raw_size);
@@ -387,7 +432,8 @@ static void process_event(union perf_event *event __unused,
387 else 432 else
388 printf("\n"); 433 printf("\n");
389 perf_event__print_ip(event, sample, machine, evsel, 434 perf_event__print_ip(event, sample, machine, evsel,
390 PRINT_FIELD(SYM), PRINT_FIELD(DSO)); 435 PRINT_FIELD(SYM), PRINT_FIELD(DSO),
436 PRINT_FIELD(SYMOFFSET));
391 } 437 }
392 438
393 printf("\n"); 439 printf("\n");
@@ -1097,7 +1143,10 @@ static const struct option options[] = {
1097 OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory", 1143 OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory",
1098 "Look for files with symbols relative to this directory"), 1144 "Look for files with symbols relative to this directory"),
1099 OPT_CALLBACK('f', "fields", NULL, "str", 1145 OPT_CALLBACK('f', "fields", NULL, "str",
1100 "comma separated output fields prepend with 'type:'. Valid types: hw,sw,trace,raw. Fields: comm,tid,pid,time,cpu,event,trace,ip,sym,dso,addr", 1146 "comma separated output fields prepend with 'type:'. "
1147 "Valid types: hw,sw,trace,raw. "
1148 "Fields: comm,tid,pid,time,cpu,event,trace,ip,sym,dso,"
1149 "addr,symoff",
1101 parse_output_fields), 1150 parse_output_fields),
1102 OPT_BOOLEAN('a', "all-cpus", &system_wide, 1151 OPT_BOOLEAN('a', "all-cpus", &system_wide,
1103 "system-wide collection from all CPUs"), 1152 "system-wide collection from all CPUs"),
@@ -1106,6 +1155,9 @@ static const struct option options[] = {
1106 "only display events for these comms"), 1155 "only display events for these comms"),
1107 OPT_BOOLEAN('I', "show-info", &show_full_info, 1156 OPT_BOOLEAN('I', "show-info", &show_full_info,
1108 "display extended information from perf.data file"), 1157 "display extended information from perf.data file"),
1158 OPT_BOOLEAN('\0', "show-kernel-path", &symbol_conf.show_kernel_path,
1159 "Show the path of [kernel.kallsyms]"),
1160
1109 OPT_END() 1161 OPT_END()
1110}; 1162};
1111 1163
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index f5d2a63eba66..ea40e4e8b227 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -182,8 +182,8 @@ static int run_count = 1;
182static bool no_inherit = false; 182static bool no_inherit = false;
183static bool scale = true; 183static bool scale = true;
184static bool no_aggr = false; 184static bool no_aggr = false;
185static pid_t target_pid = -1; 185static const char *target_pid;
186static pid_t target_tid = -1; 186static const char *target_tid;
187static pid_t child_pid = -1; 187static pid_t child_pid = -1;
188static bool null_run = false; 188static bool null_run = false;
189static int detailed_run = 0; 189static int detailed_run = 0;
@@ -296,7 +296,7 @@ static int create_perf_stat_counter(struct perf_evsel *evsel,
296 if (system_wide) 296 if (system_wide)
297 return perf_evsel__open_per_cpu(evsel, evsel_list->cpus, 297 return perf_evsel__open_per_cpu(evsel, evsel_list->cpus,
298 group, group_fd); 298 group, group_fd);
299 if (target_pid == -1 && target_tid == -1) { 299 if (!target_pid && !target_tid) {
300 attr->disabled = 1; 300 attr->disabled = 1;
301 attr->enable_on_exec = 1; 301 attr->enable_on_exec = 1;
302 } 302 }
@@ -446,7 +446,7 @@ static int run_perf_stat(int argc __used, const char **argv)
446 exit(-1); 446 exit(-1);
447 } 447 }
448 448
449 if (target_tid == -1 && target_pid == -1 && !system_wide) 449 if (!target_tid && !target_pid && !system_wide)
450 evsel_list->threads->map[0] = child_pid; 450 evsel_list->threads->map[0] = child_pid;
451 451
452 /* 452 /*
@@ -576,6 +576,8 @@ static void nsec_printout(int cpu, struct perf_evsel *evsel, double avg)
576 if (perf_evsel__match(evsel, SOFTWARE, SW_TASK_CLOCK)) 576 if (perf_evsel__match(evsel, SOFTWARE, SW_TASK_CLOCK))
577 fprintf(output, " # %8.3f CPUs utilized ", 577 fprintf(output, " # %8.3f CPUs utilized ",
578 avg / avg_stats(&walltime_nsecs_stats)); 578 avg / avg_stats(&walltime_nsecs_stats));
579 else
580 fprintf(output, " ");
579} 581}
580 582
581/* used for get_ratio_color() */ 583/* used for get_ratio_color() */
@@ -844,12 +846,18 @@ static void abs_printout(int cpu, struct perf_evsel *evsel, double avg)
844 846
845 fprintf(output, " # %8.3f GHz ", ratio); 847 fprintf(output, " # %8.3f GHz ", ratio);
846 } else if (runtime_nsecs_stats[cpu].n != 0) { 848 } else if (runtime_nsecs_stats[cpu].n != 0) {
849 char unit = 'M';
850
847 total = avg_stats(&runtime_nsecs_stats[cpu]); 851 total = avg_stats(&runtime_nsecs_stats[cpu]);
848 852
849 if (total) 853 if (total)
850 ratio = 1000.0 * avg / total; 854 ratio = 1000.0 * avg / total;
855 if (ratio < 0.001) {
856 ratio *= 1000;
857 unit = 'K';
858 }
851 859
852 fprintf(output, " # %8.3f M/sec ", ratio); 860 fprintf(output, " # %8.3f %c/sec ", ratio, unit);
853 } else { 861 } else {
854 fprintf(output, " "); 862 fprintf(output, " ");
855 } 863 }
@@ -960,14 +968,14 @@ static void print_stat(int argc, const char **argv)
960 if (!csv_output) { 968 if (!csv_output) {
961 fprintf(output, "\n"); 969 fprintf(output, "\n");
962 fprintf(output, " Performance counter stats for "); 970 fprintf(output, " Performance counter stats for ");
963 if(target_pid == -1 && target_tid == -1) { 971 if (!target_pid && !target_tid) {
964 fprintf(output, "\'%s", argv[0]); 972 fprintf(output, "\'%s", argv[0]);
965 for (i = 1; i < argc; i++) 973 for (i = 1; i < argc; i++)
966 fprintf(output, " %s", argv[i]); 974 fprintf(output, " %s", argv[i]);
967 } else if (target_pid != -1) 975 } else if (target_pid)
968 fprintf(output, "process id \'%d", target_pid); 976 fprintf(output, "process id \'%s", target_pid);
969 else 977 else
970 fprintf(output, "thread id \'%d", target_tid); 978 fprintf(output, "thread id \'%s", target_tid);
971 979
972 fprintf(output, "\'"); 980 fprintf(output, "\'");
973 if (run_count > 1) 981 if (run_count > 1)
@@ -1041,10 +1049,10 @@ static const struct option options[] = {
1041 "event filter", parse_filter), 1049 "event filter", parse_filter),
1042 OPT_BOOLEAN('i', "no-inherit", &no_inherit, 1050 OPT_BOOLEAN('i', "no-inherit", &no_inherit,
1043 "child tasks do not inherit counters"), 1051 "child tasks do not inherit counters"),
1044 OPT_INTEGER('p', "pid", &target_pid, 1052 OPT_STRING('p', "pid", &target_pid, "pid",
1045 "stat events on existing process id"), 1053 "stat events on existing process id"),
1046 OPT_INTEGER('t', "tid", &target_tid, 1054 OPT_STRING('t', "tid", &target_tid, "tid",
1047 "stat events on existing thread id"), 1055 "stat events on existing thread id"),
1048 OPT_BOOLEAN('a', "all-cpus", &system_wide, 1056 OPT_BOOLEAN('a', "all-cpus", &system_wide,
1049 "system-wide collection from all CPUs"), 1057 "system-wide collection from all CPUs"),
1050 OPT_BOOLEAN('g', "group", &group, 1058 OPT_BOOLEAN('g', "group", &group,
@@ -1182,7 +1190,7 @@ int cmd_stat(int argc, const char **argv, const char *prefix __used)
1182 } else if (big_num_opt == 0) /* User passed --no-big-num */ 1190 } else if (big_num_opt == 0) /* User passed --no-big-num */
1183 big_num = false; 1191 big_num = false;
1184 1192
1185 if (!argc && target_pid == -1 && target_tid == -1) 1193 if (!argc && !target_pid && !target_tid)
1186 usage_with_options(stat_usage, options); 1194 usage_with_options(stat_usage, options);
1187 if (run_count <= 0) 1195 if (run_count <= 0)
1188 usage_with_options(stat_usage, options); 1196 usage_with_options(stat_usage, options);
@@ -1198,10 +1206,11 @@ int cmd_stat(int argc, const char **argv, const char *prefix __used)
1198 if (add_default_attributes()) 1206 if (add_default_attributes())
1199 goto out; 1207 goto out;
1200 1208
1201 if (target_pid != -1) 1209 if (target_pid)
1202 target_tid = target_pid; 1210 target_tid = target_pid;
1203 1211
1204 evsel_list->threads = thread_map__new(target_pid, target_tid); 1212 evsel_list->threads = thread_map__new_str(target_pid,
1213 target_tid, UINT_MAX);
1205 if (evsel_list->threads == NULL) { 1214 if (evsel_list->threads == NULL) {
1206 pr_err("Problems finding threads of monitor\n"); 1215 pr_err("Problems finding threads of monitor\n");
1207 usage_with_options(stat_usage, options); 1216 usage_with_options(stat_usage, options);
diff --git a/tools/perf/builtin-test.c b/tools/perf/builtin-test.c
index 3854e869dce1..3e087ce8daa6 100644
--- a/tools/perf/builtin-test.c
+++ b/tools/perf/builtin-test.c
@@ -15,6 +15,8 @@
15#include "util/thread_map.h" 15#include "util/thread_map.h"
16#include "../../include/linux/hw_breakpoint.h" 16#include "../../include/linux/hw_breakpoint.h"
17 17
18#include <sys/mman.h>
19
18static int vmlinux_matches_kallsyms_filter(struct map *map __used, struct symbol *sym) 20static int vmlinux_matches_kallsyms_filter(struct map *map __used, struct symbol *sym)
19{ 21{
20 bool *visited = symbol__priv(sym); 22 bool *visited = symbol__priv(sym);
@@ -276,7 +278,7 @@ static int test__open_syscall_event(void)
276 return -1; 278 return -1;
277 } 279 }
278 280
279 threads = thread_map__new(-1, getpid()); 281 threads = thread_map__new(-1, getpid(), UINT_MAX);
280 if (threads == NULL) { 282 if (threads == NULL) {
281 pr_debug("thread_map__new\n"); 283 pr_debug("thread_map__new\n");
282 return -1; 284 return -1;
@@ -342,7 +344,7 @@ static int test__open_syscall_event_on_all_cpus(void)
342 return -1; 344 return -1;
343 } 345 }
344 346
345 threads = thread_map__new(-1, getpid()); 347 threads = thread_map__new(-1, getpid(), UINT_MAX);
346 if (threads == NULL) { 348 if (threads == NULL) {
347 pr_debug("thread_map__new\n"); 349 pr_debug("thread_map__new\n");
348 return -1; 350 return -1;
@@ -490,7 +492,7 @@ static int test__basic_mmap(void)
490 expected_nr_events[i] = random() % 257; 492 expected_nr_events[i] = random() % 257;
491 } 493 }
492 494
493 threads = thread_map__new(-1, getpid()); 495 threads = thread_map__new(-1, getpid(), UINT_MAX);
494 if (threads == NULL) { 496 if (threads == NULL) {
495 pr_debug("thread_map__new\n"); 497 pr_debug("thread_map__new\n");
496 return -1; 498 return -1;
@@ -1008,12 +1010,9 @@ realloc:
1008static int test__PERF_RECORD(void) 1010static int test__PERF_RECORD(void)
1009{ 1011{
1010 struct perf_record_opts opts = { 1012 struct perf_record_opts opts = {
1011 .target_pid = -1,
1012 .target_tid = -1,
1013 .no_delay = true, 1013 .no_delay = true,
1014 .freq = 10, 1014 .freq = 10,
1015 .mmap_pages = 256, 1015 .mmap_pages = 256,
1016 .sample_id_all_avail = true,
1017 }; 1016 };
1018 cpu_set_t *cpu_mask = NULL; 1017 cpu_set_t *cpu_mask = NULL;
1019 size_t cpu_mask_size = 0; 1018 size_t cpu_mask_size = 0;
@@ -1054,7 +1053,7 @@ static int test__PERF_RECORD(void)
1054 * we're monitoring, the one forked there. 1053 * we're monitoring, the one forked there.
1055 */ 1054 */
1056 err = perf_evlist__create_maps(evlist, opts.target_pid, 1055 err = perf_evlist__create_maps(evlist, opts.target_pid,
1057 opts.target_tid, opts.cpu_list); 1056 opts.target_tid, UINT_MAX, opts.cpu_list);
1058 if (err < 0) { 1057 if (err < 0) {
1059 pr_debug("Not enough memory to create thread/cpu maps\n"); 1058 pr_debug("Not enough memory to create thread/cpu maps\n");
1060 goto out_delete_evlist; 1059 goto out_delete_evlist;
@@ -1296,6 +1295,173 @@ out:
1296 return (err < 0 || errs > 0) ? -1 : 0; 1295 return (err < 0 || errs > 0) ? -1 : 0;
1297} 1296}
1298 1297
1298
1299#if defined(__x86_64__) || defined(__i386__)
1300
1301#define barrier() asm volatile("" ::: "memory")
1302
1303static u64 rdpmc(unsigned int counter)
1304{
1305 unsigned int low, high;
1306
1307 asm volatile("rdpmc" : "=a" (low), "=d" (high) : "c" (counter));
1308
1309 return low | ((u64)high) << 32;
1310}
1311
1312static u64 rdtsc(void)
1313{
1314 unsigned int low, high;
1315
1316 asm volatile("rdtsc" : "=a" (low), "=d" (high));
1317
1318 return low | ((u64)high) << 32;
1319}
1320
1321static u64 mmap_read_self(void *addr)
1322{
1323 struct perf_event_mmap_page *pc = addr;
1324 u32 seq, idx, time_mult = 0, time_shift = 0;
1325 u64 count, cyc = 0, time_offset = 0, enabled, running, delta;
1326
1327 do {
1328 seq = pc->lock;
1329 barrier();
1330
1331 enabled = pc->time_enabled;
1332 running = pc->time_running;
1333
1334 if (enabled != running) {
1335 cyc = rdtsc();
1336 time_mult = pc->time_mult;
1337 time_shift = pc->time_shift;
1338 time_offset = pc->time_offset;
1339 }
1340
1341 idx = pc->index;
1342 count = pc->offset;
1343 if (idx)
1344 count += rdpmc(idx - 1);
1345
1346 barrier();
1347 } while (pc->lock != seq);
1348
1349 if (enabled != running) {
1350 u64 quot, rem;
1351
1352 quot = (cyc >> time_shift);
1353 rem = cyc & ((1 << time_shift) - 1);
1354 delta = time_offset + quot * time_mult +
1355 ((rem * time_mult) >> time_shift);
1356
1357 enabled += delta;
1358 if (idx)
1359 running += delta;
1360
1361 quot = count / running;
1362 rem = count % running;
1363 count = quot * enabled + (rem * enabled) / running;
1364 }
1365
1366 return count;
1367}
1368
1369/*
1370 * If the RDPMC instruction faults then signal this back to the test parent task:
1371 */
1372static void segfault_handler(int sig __used, siginfo_t *info __used, void *uc __used)
1373{
1374 exit(-1);
1375}
1376
1377static int __test__rdpmc(void)
1378{
1379 long page_size = sysconf(_SC_PAGE_SIZE);
1380 volatile int tmp = 0;
1381 u64 i, loops = 1000;
1382 int n;
1383 int fd;
1384 void *addr;
1385 struct perf_event_attr attr = {
1386 .type = PERF_TYPE_HARDWARE,
1387 .config = PERF_COUNT_HW_INSTRUCTIONS,
1388 .exclude_kernel = 1,
1389 };
1390 u64 delta_sum = 0;
1391 struct sigaction sa;
1392
1393 sigfillset(&sa.sa_mask);
1394 sa.sa_sigaction = segfault_handler;
1395 sigaction(SIGSEGV, &sa, NULL);
1396
1397 fprintf(stderr, "\n\n");
1398
1399 fd = sys_perf_event_open(&attr, 0, -1, -1, 0);
1400 if (fd < 0) {
1401 die("Error: sys_perf_event_open() syscall returned "
1402 "with %d (%s)\n", fd, strerror(errno));
1403 }
1404
1405 addr = mmap(NULL, page_size, PROT_READ, MAP_SHARED, fd, 0);
1406 if (addr == (void *)(-1)) {
1407 die("Error: mmap() syscall returned "
1408 "with (%s)\n", strerror(errno));
1409 }
1410
1411 for (n = 0; n < 6; n++) {
1412 u64 stamp, now, delta;
1413
1414 stamp = mmap_read_self(addr);
1415
1416 for (i = 0; i < loops; i++)
1417 tmp++;
1418
1419 now = mmap_read_self(addr);
1420 loops *= 10;
1421
1422 delta = now - stamp;
1423 fprintf(stderr, "%14d: %14Lu\n", n, (long long)delta);
1424
1425 delta_sum += delta;
1426 }
1427
1428 munmap(addr, page_size);
1429 close(fd);
1430
1431 fprintf(stderr, " ");
1432
1433 if (!delta_sum)
1434 return -1;
1435
1436 return 0;
1437}
1438
1439static int test__rdpmc(void)
1440{
1441 int status = 0;
1442 int wret = 0;
1443 int ret;
1444 int pid;
1445
1446 pid = fork();
1447 if (pid < 0)
1448 return -1;
1449
1450 if (!pid) {
1451 ret = __test__rdpmc();
1452
1453 exit(ret);
1454 }
1455
1456 wret = waitpid(pid, &status, 0);
1457 if (wret < 0 || status)
1458 return -1;
1459
1460 return 0;
1461}
1462
1463#endif
1464
1299static struct test { 1465static struct test {
1300 const char *desc; 1466 const char *desc;
1301 int (*func)(void); 1467 int (*func)(void);
@@ -1320,6 +1486,12 @@ static struct test {
1320 .desc = "parse events tests", 1486 .desc = "parse events tests",
1321 .func = test__parse_events, 1487 .func = test__parse_events,
1322 }, 1488 },
1489#if defined(__x86_64__) || defined(__i386__)
1490 {
1491 .desc = "x86 rdpmc test",
1492 .func = test__rdpmc,
1493 },
1494#endif
1323 { 1495 {
1324 .desc = "Validate PERF_RECORD_* events & perf_sample fields", 1496 .desc = "Validate PERF_RECORD_* events & perf_sample fields",
1325 .func = test__PERF_RECORD, 1497 .func = test__PERF_RECORD,
@@ -1412,7 +1584,5 @@ int cmd_test(int argc, const char **argv, const char *prefix __used)
1412 if (symbol__init() < 0) 1584 if (symbol__init() < 0)
1413 return -1; 1585 return -1;
1414 1586
1415 setup_pager();
1416
1417 return __cmd_test(argc, argv); 1587 return __cmd_test(argc, argv);
1418} 1588}
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index ecff31257eb3..e3c63aef8efc 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -64,7 +64,6 @@
64#include <linux/unistd.h> 64#include <linux/unistd.h>
65#include <linux/types.h> 65#include <linux/types.h>
66 66
67
68void get_term_dimensions(struct winsize *ws) 67void get_term_dimensions(struct winsize *ws)
69{ 68{
70 char *s = getenv("LINES"); 69 char *s = getenv("LINES");
@@ -544,10 +543,20 @@ static void perf_top__sort_new_samples(void *arg)
544 543
545static void *display_thread_tui(void *arg) 544static void *display_thread_tui(void *arg)
546{ 545{
546 struct perf_evsel *pos;
547 struct perf_top *top = arg; 547 struct perf_top *top = arg;
548 const char *help = "For a higher level overview, try: perf top --sort comm,dso"; 548 const char *help = "For a higher level overview, try: perf top --sort comm,dso";
549 549
550 perf_top__sort_new_samples(top); 550 perf_top__sort_new_samples(top);
551
552 /*
553 * Initialize the uid_filter_str, in the future the TUI will allow
554 * Zooming in/out UIDs. For now juse use whatever the user passed
555 * via --uid.
556 */
557 list_for_each_entry(pos, &top->evlist->entries, node)
558 pos->hists.uid_filter_str = top->uid_str;
559
551 perf_evlist__tui_browse_hists(top->evlist, help, 560 perf_evlist__tui_browse_hists(top->evlist, help,
552 perf_top__sort_new_samples, 561 perf_top__sort_new_samples,
553 top, top->delay_secs); 562 top, top->delay_secs);
@@ -668,6 +677,12 @@ static void perf_event__process_sample(struct perf_tool *tool,
668 return; 677 return;
669 } 678 }
670 679
680 if (!machine) {
681 pr_err("%u unprocessable samples recorded.",
682 top->session->hists.stats.nr_unprocessable_samples++);
683 return;
684 }
685
671 if (event->header.misc & PERF_RECORD_MISC_EXACT_IP) 686 if (event->header.misc & PERF_RECORD_MISC_EXACT_IP)
672 top->exact_samples++; 687 top->exact_samples++;
673 688
@@ -861,7 +876,7 @@ fallback_missing_features:
861 if (top->exclude_guest_missing) 876 if (top->exclude_guest_missing)
862 attr->exclude_guest = attr->exclude_host = 0; 877 attr->exclude_guest = attr->exclude_host = 0;
863retry_sample_id: 878retry_sample_id:
864 attr->sample_id_all = top->sample_id_all_avail ? 1 : 0; 879 attr->sample_id_all = top->sample_id_all_missing ? 0 : 1;
865try_again: 880try_again:
866 if (perf_evsel__open(counter, top->evlist->cpus, 881 if (perf_evsel__open(counter, top->evlist->cpus,
867 top->evlist->threads, top->group, 882 top->evlist->threads, top->group,
@@ -878,11 +893,11 @@ try_again:
878 "guest or host samples.\n"); 893 "guest or host samples.\n");
879 top->exclude_guest_missing = true; 894 top->exclude_guest_missing = true;
880 goto fallback_missing_features; 895 goto fallback_missing_features;
881 } else if (top->sample_id_all_avail) { 896 } else if (!top->sample_id_all_missing) {
882 /* 897 /*
883 * Old kernel, no attr->sample_id_type_all field 898 * Old kernel, no attr->sample_id_type_all field
884 */ 899 */
885 top->sample_id_all_avail = false; 900 top->sample_id_all_missing = true;
886 goto retry_sample_id; 901 goto retry_sample_id;
887 } 902 }
888 } 903 }
@@ -967,7 +982,7 @@ static int __cmd_top(struct perf_top *top)
967 if (ret) 982 if (ret)
968 goto out_delete; 983 goto out_delete;
969 984
970 if (top->target_tid != -1) 985 if (top->target_tid || top->uid != UINT_MAX)
971 perf_event__synthesize_thread_map(&top->tool, top->evlist->threads, 986 perf_event__synthesize_thread_map(&top->tool, top->evlist->threads,
972 perf_event__process, 987 perf_event__process,
973 &top->session->host_machine); 988 &top->session->host_machine);
@@ -1105,10 +1120,8 @@ int cmd_top(int argc, const char **argv, const char *prefix __used)
1105 struct perf_top top = { 1120 struct perf_top top = {
1106 .count_filter = 5, 1121 .count_filter = 5,
1107 .delay_secs = 2, 1122 .delay_secs = 2,
1108 .target_pid = -1, 1123 .uid = UINT_MAX,
1109 .target_tid = -1,
1110 .freq = 1000, /* 1 KHz */ 1124 .freq = 1000, /* 1 KHz */
1111 .sample_id_all_avail = true,
1112 .mmap_pages = 128, 1125 .mmap_pages = 128,
1113 .sym_pcnt_filter = 5, 1126 .sym_pcnt_filter = 5,
1114 }; 1127 };
@@ -1119,9 +1132,9 @@ int cmd_top(int argc, const char **argv, const char *prefix __used)
1119 parse_events_option), 1132 parse_events_option),
1120 OPT_INTEGER('c', "count", &top.default_interval, 1133 OPT_INTEGER('c', "count", &top.default_interval,
1121 "event period to sample"), 1134 "event period to sample"),
1122 OPT_INTEGER('p', "pid", &top.target_pid, 1135 OPT_STRING('p', "pid", &top.target_pid, "pid",
1123 "profile events on existing process id"), 1136 "profile events on existing process id"),
1124 OPT_INTEGER('t', "tid", &top.target_tid, 1137 OPT_STRING('t', "tid", &top.target_tid, "tid",
1125 "profile events on existing thread id"), 1138 "profile events on existing thread id"),
1126 OPT_BOOLEAN('a', "all-cpus", &top.system_wide, 1139 OPT_BOOLEAN('a', "all-cpus", &top.system_wide,
1127 "system-wide collection from all CPUs"), 1140 "system-wide collection from all CPUs"),
@@ -1180,6 +1193,7 @@ int cmd_top(int argc, const char **argv, const char *prefix __used)
1180 "Display raw encoding of assembly instructions (default)"), 1193 "Display raw encoding of assembly instructions (default)"),
1181 OPT_STRING('M', "disassembler-style", &disassembler_style, "disassembler style", 1194 OPT_STRING('M', "disassembler-style", &disassembler_style, "disassembler style",
1182 "Specify disassembler style (e.g. -M intel for intel syntax)"), 1195 "Specify disassembler style (e.g. -M intel for intel syntax)"),
1196 OPT_STRING('u', "uid", &top.uid_str, "user", "user to profile"),
1183 OPT_END() 1197 OPT_END()
1184 }; 1198 };
1185 1199
@@ -1205,18 +1219,22 @@ int cmd_top(int argc, const char **argv, const char *prefix __used)
1205 1219
1206 setup_browser(false); 1220 setup_browser(false);
1207 1221
1222 top.uid = parse_target_uid(top.uid_str, top.target_tid, top.target_pid);
1223 if (top.uid_str != NULL && top.uid == UINT_MAX - 1)
1224 goto out_delete_evlist;
1225
1208 /* CPU and PID are mutually exclusive */ 1226 /* CPU and PID are mutually exclusive */
1209 if (top.target_tid > 0 && top.cpu_list) { 1227 if (top.target_tid && top.cpu_list) {
1210 printf("WARNING: PID switch overriding CPU\n"); 1228 printf("WARNING: PID switch overriding CPU\n");
1211 sleep(1); 1229 sleep(1);
1212 top.cpu_list = NULL; 1230 top.cpu_list = NULL;
1213 } 1231 }
1214 1232
1215 if (top.target_pid != -1) 1233 if (top.target_pid)
1216 top.target_tid = top.target_pid; 1234 top.target_tid = top.target_pid;
1217 1235
1218 if (perf_evlist__create_maps(top.evlist, top.target_pid, 1236 if (perf_evlist__create_maps(top.evlist, top.target_pid,
1219 top.target_tid, top.cpu_list) < 0) 1237 top.target_tid, top.uid, top.cpu_list) < 0)
1220 usage_with_options(top_usage, options); 1238 usage_with_options(top_usage, options);
1221 1239
1222 if (!top.evlist->nr_entries && 1240 if (!top.evlist->nr_entries &&
@@ -1280,6 +1298,7 @@ int cmd_top(int argc, const char **argv, const char *prefix __used)
1280 1298
1281 status = __cmd_top(&top); 1299 status = __cmd_top(&top);
1282 1300
1301out_delete_evlist:
1283 perf_evlist__delete(top.evlist); 1302 perf_evlist__delete(top.evlist);
1284 1303
1285 return status; 1304 return status;
diff --git a/tools/perf/perf.h b/tools/perf/perf.h
index 16e7d20eee83..f0227e93665d 100644
--- a/tools/perf/perf.h
+++ b/tools/perf/perf.h
@@ -167,7 +167,6 @@ sys_perf_event_open(struct perf_event_attr *attr,
167 pid_t pid, int cpu, int group_fd, 167 pid_t pid, int cpu, int group_fd,
168 unsigned long flags) 168 unsigned long flags)
169{ 169{
170 attr->size = sizeof(*attr);
171 return syscall(__NR_perf_event_open, attr, pid, cpu, 170 return syscall(__NR_perf_event_open, attr, pid, cpu,
172 group_fd, flags); 171 group_fd, flags);
173} 172}
@@ -186,8 +185,9 @@ extern const char perf_version_string[];
186void pthread__unblock_sigwinch(void); 185void pthread__unblock_sigwinch(void);
187 186
188struct perf_record_opts { 187struct perf_record_opts {
189 pid_t target_pid; 188 const char *target_pid;
190 pid_t target_tid; 189 const char *target_tid;
190 uid_t uid;
191 bool call_graph; 191 bool call_graph;
192 bool group; 192 bool group;
193 bool inherit_stat; 193 bool inherit_stat;
@@ -198,7 +198,7 @@ struct perf_record_opts {
198 bool raw_samples; 198 bool raw_samples;
199 bool sample_address; 199 bool sample_address;
200 bool sample_time; 200 bool sample_time;
201 bool sample_id_all_avail; 201 bool sample_id_all_missing;
202 bool exclude_guest_missing; 202 bool exclude_guest_missing;
203 bool system_wide; 203 bool system_wide;
204 bool period; 204 bool period;
diff --git a/tools/perf/python/twatch.py b/tools/perf/python/twatch.py
index df638c438a9f..b11cca584238 100755
--- a/tools/perf/python/twatch.py
+++ b/tools/perf/python/twatch.py
@@ -19,7 +19,7 @@ def main():
19 cpus = perf.cpu_map() 19 cpus = perf.cpu_map()
20 threads = perf.thread_map() 20 threads = perf.thread_map()
21 evsel = perf.evsel(task = 1, comm = 1, mmap = 0, 21 evsel = perf.evsel(task = 1, comm = 1, mmap = 0,
22 wakeup_events = 1, sample_period = 1, 22 wakeup_events = 1, watermark = 1,
23 sample_id_all = 1, 23 sample_id_all = 1,
24 sample_type = perf.SAMPLE_PERIOD | perf.SAMPLE_TID | perf.SAMPLE_CPU | perf.SAMPLE_TID) 24 sample_type = perf.SAMPLE_PERIOD | perf.SAMPLE_TID | perf.SAMPLE_CPU | perf.SAMPLE_TID)
25 evsel.open(cpus = cpus, threads = threads); 25 evsel.open(cpus = cpus, threads = threads);
diff --git a/tools/perf/util/bitmap.c b/tools/perf/util/bitmap.c
index 5e230acae1e9..0a1adc1111fd 100644
--- a/tools/perf/util/bitmap.c
+++ b/tools/perf/util/bitmap.c
@@ -19,3 +19,13 @@ int __bitmap_weight(const unsigned long *bitmap, int bits)
19 19
20 return w; 20 return w;
21} 21}
22
23void __bitmap_or(unsigned long *dst, const unsigned long *bitmap1,
24 const unsigned long *bitmap2, int bits)
25{
26 int k;
27 int nr = BITS_TO_LONGS(bits);
28
29 for (k = 0; k < nr; k++)
30 dst[k] = bitmap1[k] | bitmap2[k];
31}
diff --git a/tools/perf/util/cpumap.c b/tools/perf/util/cpumap.c
index 6893eec693ab..adc72f09914d 100644
--- a/tools/perf/util/cpumap.c
+++ b/tools/perf/util/cpumap.c
@@ -166,6 +166,17 @@ out:
166 return cpus; 166 return cpus;
167} 167}
168 168
169size_t cpu_map__fprintf(struct cpu_map *map, FILE *fp)
170{
171 int i;
172 size_t printed = fprintf(fp, "%d cpu%s: ",
173 map->nr, map->nr > 1 ? "s" : "");
174 for (i = 0; i < map->nr; ++i)
175 printed += fprintf(fp, "%s%d", i ? ", " : "", map->map[i]);
176
177 return printed + fprintf(fp, "\n");
178}
179
169struct cpu_map *cpu_map__dummy_new(void) 180struct cpu_map *cpu_map__dummy_new(void)
170{ 181{
171 struct cpu_map *cpus = malloc(sizeof(*cpus) + sizeof(int)); 182 struct cpu_map *cpus = malloc(sizeof(*cpus) + sizeof(int));
diff --git a/tools/perf/util/cpumap.h b/tools/perf/util/cpumap.h
index 072c0a374794..c41518573c6a 100644
--- a/tools/perf/util/cpumap.h
+++ b/tools/perf/util/cpumap.h
@@ -1,6 +1,8 @@
1#ifndef __PERF_CPUMAP_H 1#ifndef __PERF_CPUMAP_H
2#define __PERF_CPUMAP_H 2#define __PERF_CPUMAP_H
3 3
4#include <stdio.h>
5
4struct cpu_map { 6struct cpu_map {
5 int nr; 7 int nr;
6 int map[]; 8 int map[];
@@ -10,4 +12,6 @@ struct cpu_map *cpu_map__new(const char *cpu_list);
10struct cpu_map *cpu_map__dummy_new(void); 12struct cpu_map *cpu_map__dummy_new(void);
11void cpu_map__delete(struct cpu_map *map); 13void cpu_map__delete(struct cpu_map *map);
12 14
15size_t cpu_map__fprintf(struct cpu_map *map, FILE *fp);
16
13#endif /* __PERF_CPUMAP_H */ 17#endif /* __PERF_CPUMAP_H */
diff --git a/tools/perf/util/ctype.c b/tools/perf/util/ctype.c
index 35073621e5de..aada3ac5e891 100644
--- a/tools/perf/util/ctype.c
+++ b/tools/perf/util/ctype.c
@@ -3,7 +3,7 @@
3 * 3 *
4 * No surprises, and works with signed and unsigned chars. 4 * No surprises, and works with signed and unsigned chars.
5 */ 5 */
6#include "cache.h" 6#include "util.h"
7 7
8enum { 8enum {
9 S = GIT_SPACE, 9 S = GIT_SPACE,
diff --git a/tools/perf/util/debugfs.c b/tools/perf/util/debugfs.c
index ffc35e748e89..dd8b19319c03 100644
--- a/tools/perf/util/debugfs.c
+++ b/tools/perf/util/debugfs.c
@@ -15,32 +15,6 @@ static const char *debugfs_known_mountpoints[] = {
15 0, 15 0,
16}; 16};
17 17
18/* use this to force a umount */
19void debugfs_force_cleanup(void)
20{
21 debugfs_find_mountpoint();
22 debugfs_premounted = 0;
23 debugfs_umount();
24}
25
26/* construct a full path to a debugfs element */
27int debugfs_make_path(const char *element, char *buffer, int size)
28{
29 int len;
30
31 if (strlen(debugfs_mountpoint) == 0) {
32 buffer[0] = '\0';
33 return -1;
34 }
35
36 len = strlen(debugfs_mountpoint) + strlen(element) + 1;
37 if (len >= size)
38 return len+1;
39
40 snprintf(buffer, size-1, "%s/%s", debugfs_mountpoint, element);
41 return 0;
42}
43
44static int debugfs_found; 18static int debugfs_found;
45 19
46/* find the path to the mounted debugfs */ 20/* find the path to the mounted debugfs */
@@ -97,17 +71,6 @@ int debugfs_valid_mountpoint(const char *debugfs)
97 return 0; 71 return 0;
98} 72}
99 73
100
101int debugfs_valid_entry(const char *path)
102{
103 struct stat st;
104
105 if (stat(path, &st))
106 return -errno;
107
108 return 0;
109}
110
111static void debugfs_set_tracing_events_path(const char *mountpoint) 74static void debugfs_set_tracing_events_path(const char *mountpoint)
112{ 75{
113 snprintf(tracing_events_path, sizeof(tracing_events_path), "%s/%s", 76 snprintf(tracing_events_path, sizeof(tracing_events_path), "%s/%s",
@@ -149,107 +112,3 @@ void debugfs_set_path(const char *mountpoint)
149 snprintf(debugfs_mountpoint, sizeof(debugfs_mountpoint), "%s", mountpoint); 112 snprintf(debugfs_mountpoint, sizeof(debugfs_mountpoint), "%s", mountpoint);
150 debugfs_set_tracing_events_path(mountpoint); 113 debugfs_set_tracing_events_path(mountpoint);
151} 114}
152
153/* umount the debugfs */
154
155int debugfs_umount(void)
156{
157 char umountcmd[128];
158 int ret;
159
160 /* if it was already mounted, leave it */
161 if (debugfs_premounted)
162 return 0;
163
164 /* make sure it's a valid mount point */
165 ret = debugfs_valid_mountpoint(debugfs_mountpoint);
166 if (ret)
167 return ret;
168
169 snprintf(umountcmd, sizeof(umountcmd),
170 "/bin/umount %s", debugfs_mountpoint);
171 return system(umountcmd);
172}
173
174int debugfs_write(const char *entry, const char *value)
175{
176 char path[PATH_MAX + 1];
177 int ret, count;
178 int fd;
179
180 /* construct the path */
181 snprintf(path, sizeof(path), "%s/%s", debugfs_mountpoint, entry);
182
183 /* verify that it exists */
184 ret = debugfs_valid_entry(path);
185 if (ret)
186 return ret;
187
188 /* get how many chars we're going to write */
189 count = strlen(value);
190
191 /* open the debugfs entry */
192 fd = open(path, O_RDWR);
193 if (fd < 0)
194 return -errno;
195
196 while (count > 0) {
197 /* write it */
198 ret = write(fd, value, count);
199 if (ret <= 0) {
200 if (ret == EAGAIN)
201 continue;
202 close(fd);
203 return -errno;
204 }
205 count -= ret;
206 }
207
208 /* close it */
209 close(fd);
210
211 /* return success */
212 return 0;
213}
214
215/*
216 * read a debugfs entry
217 * returns the number of chars read or a negative errno
218 */
219int debugfs_read(const char *entry, char *buffer, size_t size)
220{
221 char path[PATH_MAX + 1];
222 int ret;
223 int fd;
224
225 /* construct the path */
226 snprintf(path, sizeof(path), "%s/%s", debugfs_mountpoint, entry);
227
228 /* verify that it exists */
229 ret = debugfs_valid_entry(path);
230 if (ret)
231 return ret;
232
233 /* open the debugfs entry */
234 fd = open(path, O_RDONLY);
235 if (fd < 0)
236 return -errno;
237
238 do {
239 /* read it */
240 ret = read(fd, buffer, size);
241 if (ret == 0) {
242 close(fd);
243 return EOF;
244 }
245 } while (ret < 0 && errno == EAGAIN);
246
247 /* close it */
248 close(fd);
249
250 /* make *sure* there's a null character at the end */
251 buffer[ret] = '\0';
252
253 /* return the number of chars read */
254 return ret;
255}
diff --git a/tools/perf/util/debugfs.h b/tools/perf/util/debugfs.h
index 4a878f735eb0..68f3e87ec57f 100644
--- a/tools/perf/util/debugfs.h
+++ b/tools/perf/util/debugfs.h
@@ -3,14 +3,8 @@
3 3
4const char *debugfs_find_mountpoint(void); 4const char *debugfs_find_mountpoint(void);
5int debugfs_valid_mountpoint(const char *debugfs); 5int debugfs_valid_mountpoint(const char *debugfs);
6int debugfs_valid_entry(const char *path);
7char *debugfs_mount(const char *mountpoint); 6char *debugfs_mount(const char *mountpoint);
8int debugfs_umount(void);
9void debugfs_set_path(const char *mountpoint); 7void debugfs_set_path(const char *mountpoint);
10int debugfs_write(const char *entry, const char *value);
11int debugfs_read(const char *entry, char *buffer, size_t size);
12void debugfs_force_cleanup(void);
13int debugfs_make_path(const char *element, char *buffer, int size);
14 8
15extern char debugfs_mountpoint[]; 9extern char debugfs_mountpoint[];
16extern char tracing_events_path[]; 10extern char tracing_events_path[];
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index ea32a061f1c8..f8da9fada002 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -97,9 +97,9 @@ void perf_evlist__add(struct perf_evlist *evlist, struct perf_evsel *entry)
97 ++evlist->nr_entries; 97 ++evlist->nr_entries;
98} 98}
99 99
100static void perf_evlist__splice_list_tail(struct perf_evlist *evlist, 100void perf_evlist__splice_list_tail(struct perf_evlist *evlist,
101 struct list_head *list, 101 struct list_head *list,
102 int nr_entries) 102 int nr_entries)
103{ 103{
104 list_splice_tail(list, &evlist->entries); 104 list_splice_tail(list, &evlist->entries);
105 evlist->nr_entries += nr_entries; 105 evlist->nr_entries += nr_entries;
@@ -597,15 +597,15 @@ int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages,
597 return perf_evlist__mmap_per_cpu(evlist, prot, mask); 597 return perf_evlist__mmap_per_cpu(evlist, prot, mask);
598} 598}
599 599
600int perf_evlist__create_maps(struct perf_evlist *evlist, pid_t target_pid, 600int perf_evlist__create_maps(struct perf_evlist *evlist, const char *target_pid,
601 pid_t target_tid, const char *cpu_list) 601 const char *target_tid, uid_t uid, const char *cpu_list)
602{ 602{
603 evlist->threads = thread_map__new(target_pid, target_tid); 603 evlist->threads = thread_map__new_str(target_pid, target_tid, uid);
604 604
605 if (evlist->threads == NULL) 605 if (evlist->threads == NULL)
606 return -1; 606 return -1;
607 607
608 if (cpu_list == NULL && target_tid != -1) 608 if (uid != UINT_MAX || (cpu_list == NULL && target_tid))
609 evlist->cpus = cpu_map__dummy_new(); 609 evlist->cpus = cpu_map__dummy_new();
610 else 610 else
611 evlist->cpus = cpu_map__new(cpu_list); 611 evlist->cpus = cpu_map__new(cpu_list);
@@ -824,7 +824,7 @@ int perf_evlist__prepare_workload(struct perf_evlist *evlist,
824 exit(-1); 824 exit(-1);
825 } 825 }
826 826
827 if (!opts->system_wide && opts->target_tid == -1 && opts->target_pid == -1) 827 if (!opts->system_wide && !opts->target_tid && !opts->target_pid)
828 evlist->threads->map[0] = evlist->workload.pid; 828 evlist->threads->map[0] = evlist->workload.pid;
829 829
830 close(child_ready_pipe[1]); 830 close(child_ready_pipe[1]);
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
index 8922aeed0467..21f1c9e57f13 100644
--- a/tools/perf/util/evlist.h
+++ b/tools/perf/util/evlist.h
@@ -106,8 +106,8 @@ static inline void perf_evlist__set_maps(struct perf_evlist *evlist,
106 evlist->threads = threads; 106 evlist->threads = threads;
107} 107}
108 108
109int perf_evlist__create_maps(struct perf_evlist *evlist, pid_t target_pid, 109int perf_evlist__create_maps(struct perf_evlist *evlist, const char *target_pid,
110 pid_t target_tid, const char *cpu_list); 110 const char *tid, uid_t uid, const char *cpu_list);
111void perf_evlist__delete_maps(struct perf_evlist *evlist); 111void perf_evlist__delete_maps(struct perf_evlist *evlist);
112int perf_evlist__set_filters(struct perf_evlist *evlist); 112int perf_evlist__set_filters(struct perf_evlist *evlist);
113 113
@@ -117,4 +117,9 @@ u16 perf_evlist__id_hdr_size(const struct perf_evlist *evlist);
117 117
118bool perf_evlist__valid_sample_type(const struct perf_evlist *evlist); 118bool perf_evlist__valid_sample_type(const struct perf_evlist *evlist);
119bool perf_evlist__valid_sample_id_all(const struct perf_evlist *evlist); 119bool perf_evlist__valid_sample_id_all(const struct perf_evlist *evlist);
120
121void perf_evlist__splice_list_tail(struct perf_evlist *evlist,
122 struct list_head *list,
123 int nr_entries);
124
120#endif /* __PERF_EVLIST_H */ 125#endif /* __PERF_EVLIST_H */
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 7132ee834e0e..302d49a9f985 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -68,7 +68,7 @@ void perf_evsel__config(struct perf_evsel *evsel, struct perf_record_opts *opts)
68 struct perf_event_attr *attr = &evsel->attr; 68 struct perf_event_attr *attr = &evsel->attr;
69 int track = !evsel->idx; /* only the first counter needs these */ 69 int track = !evsel->idx; /* only the first counter needs these */
70 70
71 attr->sample_id_all = opts->sample_id_all_avail ? 1 : 0; 71 attr->sample_id_all = opts->sample_id_all_missing ? 0 : 1;
72 attr->inherit = !opts->no_inherit; 72 attr->inherit = !opts->no_inherit;
73 attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED | 73 attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED |
74 PERF_FORMAT_TOTAL_TIME_RUNNING | 74 PERF_FORMAT_TOTAL_TIME_RUNNING |
@@ -111,7 +111,7 @@ void perf_evsel__config(struct perf_evsel *evsel, struct perf_record_opts *opts)
111 if (opts->period) 111 if (opts->period)
112 attr->sample_type |= PERF_SAMPLE_PERIOD; 112 attr->sample_type |= PERF_SAMPLE_PERIOD;
113 113
114 if (opts->sample_id_all_avail && 114 if (!opts->sample_id_all_missing &&
115 (opts->sample_time || opts->system_wide || 115 (opts->sample_time || opts->system_wide ||
116 !opts->no_inherit || opts->cpu_list)) 116 !opts->no_inherit || opts->cpu_list))
117 attr->sample_type |= PERF_SAMPLE_TIME; 117 attr->sample_type |= PERF_SAMPLE_TIME;
@@ -130,7 +130,7 @@ void perf_evsel__config(struct perf_evsel *evsel, struct perf_record_opts *opts)
130 attr->mmap = track; 130 attr->mmap = track;
131 attr->comm = track; 131 attr->comm = track;
132 132
133 if (opts->target_pid == -1 && opts->target_tid == -1 && !opts->system_wide) { 133 if (!opts->target_pid && !opts->target_tid && !opts->system_wide) {
134 attr->disabled = 1; 134 attr->disabled = 1;
135 attr->enable_on_exec = 1; 135 attr->enable_on_exec = 1;
136 } 136 }
@@ -536,7 +536,7 @@ int perf_event__parse_sample(const union perf_event *event, u64 type,
536 } 536 }
537 537
538 if (type & PERF_SAMPLE_READ) { 538 if (type & PERF_SAMPLE_READ) {
539 fprintf(stderr, "PERF_SAMPLE_READ is unsuported for now\n"); 539 fprintf(stderr, "PERF_SAMPLE_READ is unsupported for now\n");
540 return -1; 540 return -1;
541 } 541 }
542 542
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index ecd7f4dd7eea..9f867d96c6a5 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -63,9 +63,20 @@ char *perf_header__find_event(u64 id)
63 return NULL; 63 return NULL;
64} 64}
65 65
66static const char *__perf_magic = "PERFFILE"; 66/*
67 * magic2 = "PERFILE2"
68 * must be a numerical value to let the endianness
69 * determine the memory layout. That way we are able
70 * to detect endianness when reading the perf.data file
71 * back.
72 *
73 * we check for legacy (PERFFILE) format.
74 */
75static const char *__perf_magic1 = "PERFFILE";
76static const u64 __perf_magic2 = 0x32454c4946524550ULL;
77static const u64 __perf_magic2_sw = 0x50455246494c4532ULL;
67 78
68#define PERF_MAGIC (*(u64 *)__perf_magic) 79#define PERF_MAGIC __perf_magic2
69 80
70struct perf_file_attr { 81struct perf_file_attr {
71 struct perf_event_attr attr; 82 struct perf_event_attr attr;
@@ -1305,25 +1316,198 @@ static void print_cpuid(struct perf_header *ph, int fd, FILE *fp)
1305 free(str); 1316 free(str);
1306} 1317}
1307 1318
1319static int __event_process_build_id(struct build_id_event *bev,
1320 char *filename,
1321 struct perf_session *session)
1322{
1323 int err = -1;
1324 struct list_head *head;
1325 struct machine *machine;
1326 u16 misc;
1327 struct dso *dso;
1328 enum dso_kernel_type dso_type;
1329
1330 machine = perf_session__findnew_machine(session, bev->pid);
1331 if (!machine)
1332 goto out;
1333
1334 misc = bev->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
1335
1336 switch (misc) {
1337 case PERF_RECORD_MISC_KERNEL:
1338 dso_type = DSO_TYPE_KERNEL;
1339 head = &machine->kernel_dsos;
1340 break;
1341 case PERF_RECORD_MISC_GUEST_KERNEL:
1342 dso_type = DSO_TYPE_GUEST_KERNEL;
1343 head = &machine->kernel_dsos;
1344 break;
1345 case PERF_RECORD_MISC_USER:
1346 case PERF_RECORD_MISC_GUEST_USER:
1347 dso_type = DSO_TYPE_USER;
1348 head = &machine->user_dsos;
1349 break;
1350 default:
1351 goto out;
1352 }
1353
1354 dso = __dsos__findnew(head, filename);
1355 if (dso != NULL) {
1356 char sbuild_id[BUILD_ID_SIZE * 2 + 1];
1357
1358 dso__set_build_id(dso, &bev->build_id);
1359
1360 if (filename[0] == '[')
1361 dso->kernel = dso_type;
1362
1363 build_id__sprintf(dso->build_id, sizeof(dso->build_id),
1364 sbuild_id);
1365 pr_debug("build id event received for %s: %s\n",
1366 dso->long_name, sbuild_id);
1367 }
1368
1369 err = 0;
1370out:
1371 return err;
1372}
1373
1374static int perf_header__read_build_ids_abi_quirk(struct perf_header *header,
1375 int input, u64 offset, u64 size)
1376{
1377 struct perf_session *session = container_of(header, struct perf_session, header);
1378 struct {
1379 struct perf_event_header header;
1380 u8 build_id[ALIGN(BUILD_ID_SIZE, sizeof(u64))];
1381 char filename[0];
1382 } old_bev;
1383 struct build_id_event bev;
1384 char filename[PATH_MAX];
1385 u64 limit = offset + size;
1386
1387 while (offset < limit) {
1388 ssize_t len;
1389
1390 if (read(input, &old_bev, sizeof(old_bev)) != sizeof(old_bev))
1391 return -1;
1392
1393 if (header->needs_swap)
1394 perf_event_header__bswap(&old_bev.header);
1395
1396 len = old_bev.header.size - sizeof(old_bev);
1397 if (read(input, filename, len) != len)
1398 return -1;
1399
1400 bev.header = old_bev.header;
1401
1402 /*
1403 * As the pid is the missing value, we need to fill
1404 * it properly. The header.misc value give us nice hint.
1405 */
1406 bev.pid = HOST_KERNEL_ID;
1407 if (bev.header.misc == PERF_RECORD_MISC_GUEST_USER ||
1408 bev.header.misc == PERF_RECORD_MISC_GUEST_KERNEL)
1409 bev.pid = DEFAULT_GUEST_KERNEL_ID;
1410
1411 memcpy(bev.build_id, old_bev.build_id, sizeof(bev.build_id));
1412 __event_process_build_id(&bev, filename, session);
1413
1414 offset += bev.header.size;
1415 }
1416
1417 return 0;
1418}
1419
1420static int perf_header__read_build_ids(struct perf_header *header,
1421 int input, u64 offset, u64 size)
1422{
1423 struct perf_session *session = container_of(header, struct perf_session, header);
1424 struct build_id_event bev;
1425 char filename[PATH_MAX];
1426 u64 limit = offset + size, orig_offset = offset;
1427 int err = -1;
1428
1429 while (offset < limit) {
1430 ssize_t len;
1431
1432 if (read(input, &bev, sizeof(bev)) != sizeof(bev))
1433 goto out;
1434
1435 if (header->needs_swap)
1436 perf_event_header__bswap(&bev.header);
1437
1438 len = bev.header.size - sizeof(bev);
1439 if (read(input, filename, len) != len)
1440 goto out;
1441 /*
1442 * The a1645ce1 changeset:
1443 *
1444 * "perf: 'perf kvm' tool for monitoring guest performance from host"
1445 *
1446 * Added a field to struct build_id_event that broke the file
1447 * format.
1448 *
1449 * Since the kernel build-id is the first entry, process the
1450 * table using the old format if the well known
1451 * '[kernel.kallsyms]' string for the kernel build-id has the
1452 * first 4 characters chopped off (where the pid_t sits).
1453 */
1454 if (memcmp(filename, "nel.kallsyms]", 13) == 0) {
1455 if (lseek(input, orig_offset, SEEK_SET) == (off_t)-1)
1456 return -1;
1457 return perf_header__read_build_ids_abi_quirk(header, input, offset, size);
1458 }
1459
1460 __event_process_build_id(&bev, filename, session);
1461
1462 offset += bev.header.size;
1463 }
1464 err = 0;
1465out:
1466 return err;
1467}
1468
1469static int process_trace_info(struct perf_file_section *section __unused,
1470 struct perf_header *ph __unused,
1471 int feat __unused, int fd)
1472{
1473 trace_report(fd, false);
1474 return 0;
1475}
1476
1477static int process_build_id(struct perf_file_section *section,
1478 struct perf_header *ph,
1479 int feat __unused, int fd)
1480{
1481 if (perf_header__read_build_ids(ph, fd, section->offset, section->size))
1482 pr_debug("Failed to read buildids, continuing...\n");
1483 return 0;
1484}
1485
1308struct feature_ops { 1486struct feature_ops {
1309 int (*write)(int fd, struct perf_header *h, struct perf_evlist *evlist); 1487 int (*write)(int fd, struct perf_header *h, struct perf_evlist *evlist);
1310 void (*print)(struct perf_header *h, int fd, FILE *fp); 1488 void (*print)(struct perf_header *h, int fd, FILE *fp);
1489 int (*process)(struct perf_file_section *section,
1490 struct perf_header *h, int feat, int fd);
1311 const char *name; 1491 const char *name;
1312 bool full_only; 1492 bool full_only;
1313}; 1493};
1314 1494
1315#define FEAT_OPA(n, func) \ 1495#define FEAT_OPA(n, func) \
1316 [n] = { .name = #n, .write = write_##func, .print = print_##func } 1496 [n] = { .name = #n, .write = write_##func, .print = print_##func }
1497#define FEAT_OPP(n, func) \
1498 [n] = { .name = #n, .write = write_##func, .print = print_##func, \
1499 .process = process_##func }
1317#define FEAT_OPF(n, func) \ 1500#define FEAT_OPF(n, func) \
1318 [n] = { .name = #n, .write = write_##func, .print = print_##func, .full_only = true } 1501 [n] = { .name = #n, .write = write_##func, .print = print_##func, \
1502 .full_only = true }
1319 1503
1320/* feature_ops not implemented: */ 1504/* feature_ops not implemented: */
1321#define print_trace_info NULL 1505#define print_trace_info NULL
1322#define print_build_id NULL 1506#define print_build_id NULL
1323 1507
1324static const struct feature_ops feat_ops[HEADER_LAST_FEATURE] = { 1508static const struct feature_ops feat_ops[HEADER_LAST_FEATURE] = {
1325 FEAT_OPA(HEADER_TRACE_INFO, trace_info), 1509 FEAT_OPP(HEADER_TRACE_INFO, trace_info),
1326 FEAT_OPA(HEADER_BUILD_ID, build_id), 1510 FEAT_OPP(HEADER_BUILD_ID, build_id),
1327 FEAT_OPA(HEADER_HOSTNAME, hostname), 1511 FEAT_OPA(HEADER_HOSTNAME, hostname),
1328 FEAT_OPA(HEADER_OSRELEASE, osrelease), 1512 FEAT_OPA(HEADER_OSRELEASE, osrelease),
1329 FEAT_OPA(HEADER_VERSION, version), 1513 FEAT_OPA(HEADER_VERSION, version),
@@ -1620,24 +1804,59 @@ out_free:
1620 return err; 1804 return err;
1621} 1805}
1622 1806
1807static int check_magic_endian(u64 *magic, struct perf_file_header *header,
1808 struct perf_header *ph)
1809{
1810 int ret;
1811
1812 /* check for legacy format */
1813 ret = memcmp(magic, __perf_magic1, sizeof(*magic));
1814 if (ret == 0) {
1815 pr_debug("legacy perf.data format\n");
1816 if (!header)
1817 return -1;
1818
1819 if (header->attr_size != sizeof(struct perf_file_attr)) {
1820 u64 attr_size = bswap_64(header->attr_size);
1821
1822 if (attr_size != sizeof(struct perf_file_attr))
1823 return -1;
1824
1825 ph->needs_swap = true;
1826 }
1827 return 0;
1828 }
1829
1830 /* check magic number with same endianness */
1831 if (*magic == __perf_magic2)
1832 return 0;
1833
1834 /* check magic number but opposite endianness */
1835 if (*magic != __perf_magic2_sw)
1836 return -1;
1837
1838 ph->needs_swap = true;
1839
1840 return 0;
1841}
1842
1623int perf_file_header__read(struct perf_file_header *header, 1843int perf_file_header__read(struct perf_file_header *header,
1624 struct perf_header *ph, int fd) 1844 struct perf_header *ph, int fd)
1625{ 1845{
1846 int ret;
1847
1626 lseek(fd, 0, SEEK_SET); 1848 lseek(fd, 0, SEEK_SET);
1627 1849
1628 if (readn(fd, header, sizeof(*header)) <= 0 || 1850 ret = readn(fd, header, sizeof(*header));
1629 memcmp(&header->magic, __perf_magic, sizeof(header->magic))) 1851 if (ret <= 0)
1630 return -1; 1852 return -1;
1631 1853
1632 if (header->attr_size != sizeof(struct perf_file_attr)) { 1854 if (check_magic_endian(&header->magic, header, ph) < 0)
1633 u64 attr_size = bswap_64(header->attr_size); 1855 return -1;
1634
1635 if (attr_size != sizeof(struct perf_file_attr))
1636 return -1;
1637 1856
1857 if (ph->needs_swap) {
1638 mem_bswap_64(header, offsetof(struct perf_file_header, 1858 mem_bswap_64(header, offsetof(struct perf_file_header,
1639 adds_features)); 1859 adds_features));
1640 ph->needs_swap = true;
1641 } 1860 }
1642 1861
1643 if (header->size != sizeof(*header)) { 1862 if (header->size != sizeof(*header)) {
@@ -1689,156 +1908,6 @@ int perf_file_header__read(struct perf_file_header *header,
1689 return 0; 1908 return 0;
1690} 1909}
1691 1910
1692static int __event_process_build_id(struct build_id_event *bev,
1693 char *filename,
1694 struct perf_session *session)
1695{
1696 int err = -1;
1697 struct list_head *head;
1698 struct machine *machine;
1699 u16 misc;
1700 struct dso *dso;
1701 enum dso_kernel_type dso_type;
1702
1703 machine = perf_session__findnew_machine(session, bev->pid);
1704 if (!machine)
1705 goto out;
1706
1707 misc = bev->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
1708
1709 switch (misc) {
1710 case PERF_RECORD_MISC_KERNEL:
1711 dso_type = DSO_TYPE_KERNEL;
1712 head = &machine->kernel_dsos;
1713 break;
1714 case PERF_RECORD_MISC_GUEST_KERNEL:
1715 dso_type = DSO_TYPE_GUEST_KERNEL;
1716 head = &machine->kernel_dsos;
1717 break;
1718 case PERF_RECORD_MISC_USER:
1719 case PERF_RECORD_MISC_GUEST_USER:
1720 dso_type = DSO_TYPE_USER;
1721 head = &machine->user_dsos;
1722 break;
1723 default:
1724 goto out;
1725 }
1726
1727 dso = __dsos__findnew(head, filename);
1728 if (dso != NULL) {
1729 char sbuild_id[BUILD_ID_SIZE * 2 + 1];
1730
1731 dso__set_build_id(dso, &bev->build_id);
1732
1733 if (filename[0] == '[')
1734 dso->kernel = dso_type;
1735
1736 build_id__sprintf(dso->build_id, sizeof(dso->build_id),
1737 sbuild_id);
1738 pr_debug("build id event received for %s: %s\n",
1739 dso->long_name, sbuild_id);
1740 }
1741
1742 err = 0;
1743out:
1744 return err;
1745}
1746
1747static int perf_header__read_build_ids_abi_quirk(struct perf_header *header,
1748 int input, u64 offset, u64 size)
1749{
1750 struct perf_session *session = container_of(header, struct perf_session, header);
1751 struct {
1752 struct perf_event_header header;
1753 u8 build_id[ALIGN(BUILD_ID_SIZE, sizeof(u64))];
1754 char filename[0];
1755 } old_bev;
1756 struct build_id_event bev;
1757 char filename[PATH_MAX];
1758 u64 limit = offset + size;
1759
1760 while (offset < limit) {
1761 ssize_t len;
1762
1763 if (read(input, &old_bev, sizeof(old_bev)) != sizeof(old_bev))
1764 return -1;
1765
1766 if (header->needs_swap)
1767 perf_event_header__bswap(&old_bev.header);
1768
1769 len = old_bev.header.size - sizeof(old_bev);
1770 if (read(input, filename, len) != len)
1771 return -1;
1772
1773 bev.header = old_bev.header;
1774
1775 /*
1776 * As the pid is the missing value, we need to fill
1777 * it properly. The header.misc value give us nice hint.
1778 */
1779 bev.pid = HOST_KERNEL_ID;
1780 if (bev.header.misc == PERF_RECORD_MISC_GUEST_USER ||
1781 bev.header.misc == PERF_RECORD_MISC_GUEST_KERNEL)
1782 bev.pid = DEFAULT_GUEST_KERNEL_ID;
1783
1784 memcpy(bev.build_id, old_bev.build_id, sizeof(bev.build_id));
1785 __event_process_build_id(&bev, filename, session);
1786
1787 offset += bev.header.size;
1788 }
1789
1790 return 0;
1791}
1792
1793static int perf_header__read_build_ids(struct perf_header *header,
1794 int input, u64 offset, u64 size)
1795{
1796 struct perf_session *session = container_of(header, struct perf_session, header);
1797 struct build_id_event bev;
1798 char filename[PATH_MAX];
1799 u64 limit = offset + size, orig_offset = offset;
1800 int err = -1;
1801
1802 while (offset < limit) {
1803 ssize_t len;
1804
1805 if (read(input, &bev, sizeof(bev)) != sizeof(bev))
1806 goto out;
1807
1808 if (header->needs_swap)
1809 perf_event_header__bswap(&bev.header);
1810
1811 len = bev.header.size - sizeof(bev);
1812 if (read(input, filename, len) != len)
1813 goto out;
1814 /*
1815 * The a1645ce1 changeset:
1816 *
1817 * "perf: 'perf kvm' tool for monitoring guest performance from host"
1818 *
1819 * Added a field to struct build_id_event that broke the file
1820 * format.
1821 *
1822 * Since the kernel build-id is the first entry, process the
1823 * table using the old format if the well known
1824 * '[kernel.kallsyms]' string for the kernel build-id has the
1825 * first 4 characters chopped off (where the pid_t sits).
1826 */
1827 if (memcmp(filename, "nel.kallsyms]", 13) == 0) {
1828 if (lseek(input, orig_offset, SEEK_SET) == (off_t)-1)
1829 return -1;
1830 return perf_header__read_build_ids_abi_quirk(header, input, offset, size);
1831 }
1832
1833 __event_process_build_id(&bev, filename, session);
1834
1835 offset += bev.header.size;
1836 }
1837 err = 0;
1838out:
1839 return err;
1840}
1841
1842static int perf_file_section__process(struct perf_file_section *section, 1911static int perf_file_section__process(struct perf_file_section *section,
1843 struct perf_header *ph, 1912 struct perf_header *ph,
1844 int feat, int fd, void *data __used) 1913 int feat, int fd, void *data __used)
@@ -1854,27 +1923,23 @@ static int perf_file_section__process(struct perf_file_section *section,
1854 return 0; 1923 return 0;
1855 } 1924 }
1856 1925
1857 switch (feat) { 1926 if (!feat_ops[feat].process)
1858 case HEADER_TRACE_INFO: 1927 return 0;
1859 trace_report(fd, false);
1860 break;
1861 case HEADER_BUILD_ID:
1862 if (perf_header__read_build_ids(ph, fd, section->offset, section->size))
1863 pr_debug("Failed to read buildids, continuing...\n");
1864 break;
1865 default:
1866 break;
1867 }
1868 1928
1869 return 0; 1929 return feat_ops[feat].process(section, ph, feat, fd);
1870} 1930}
1871 1931
1872static int perf_file_header__read_pipe(struct perf_pipe_file_header *header, 1932static int perf_file_header__read_pipe(struct perf_pipe_file_header *header,
1873 struct perf_header *ph, int fd, 1933 struct perf_header *ph, int fd,
1874 bool repipe) 1934 bool repipe)
1875{ 1935{
1876 if (readn(fd, header, sizeof(*header)) <= 0 || 1936 int ret;
1877 memcmp(&header->magic, __perf_magic, sizeof(header->magic))) 1937
1938 ret = readn(fd, header, sizeof(*header));
1939 if (ret <= 0)
1940 return -1;
1941
1942 if (check_magic_endian(&header->magic, NULL, ph) < 0)
1878 return -1; 1943 return -1;
1879 1944
1880 if (repipe && do_write(STDOUT_FILENO, header, sizeof(*header)) < 0) 1945 if (repipe && do_write(STDOUT_FILENO, header, sizeof(*header)) < 0)
diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h
index ac4ec956024e..e68f617d082f 100644
--- a/tools/perf/util/header.h
+++ b/tools/perf/util/header.h
@@ -11,6 +11,7 @@
11 11
12enum { 12enum {
13 HEADER_RESERVED = 0, /* always cleared */ 13 HEADER_RESERVED = 0, /* always cleared */
14 HEADER_FIRST_FEATURE = 1,
14 HEADER_TRACE_INFO = 1, 15 HEADER_TRACE_INFO = 1,
15 HEADER_BUILD_ID, 16 HEADER_BUILD_ID,
16 17
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index f55f0a8d1f81..48e5acd1e862 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -32,6 +32,7 @@ struct events_stats {
32 u32 nr_unknown_events; 32 u32 nr_unknown_events;
33 u32 nr_invalid_chains; 33 u32 nr_invalid_chains;
34 u32 nr_unknown_id; 34 u32 nr_unknown_id;
35 u32 nr_unprocessable_samples;
35}; 36};
36 37
37enum hist_column { 38enum hist_column {
@@ -55,6 +56,7 @@ struct hists {
55 u64 nr_entries; 56 u64 nr_entries;
56 const struct thread *thread_filter; 57 const struct thread *thread_filter;
57 const struct dso *dso_filter; 58 const struct dso *dso_filter;
59 const char *uid_filter_str;
58 pthread_mutex_t lock; 60 pthread_mutex_t lock;
59 struct events_stats stats; 61 struct events_stats stats;
60 u64 event_stream; 62 u64 event_stream;
diff --git a/tools/perf/util/include/asm/dwarf2.h b/tools/perf/util/include/asm/dwarf2.h
index bb4198e7837a..afe38199e922 100644
--- a/tools/perf/util/include/asm/dwarf2.h
+++ b/tools/perf/util/include/asm/dwarf2.h
@@ -2,10 +2,12 @@
2#ifndef PERF_DWARF2_H 2#ifndef PERF_DWARF2_H
3#define PERF_DWARF2_H 3#define PERF_DWARF2_H
4 4
5/* dwarf2.h ... dummy header file for including arch/x86/lib/memcpy_64.S */ 5/* dwarf2.h ... dummy header file for including arch/x86/lib/mem{cpy,set}_64.S */
6 6
7#define CFI_STARTPROC 7#define CFI_STARTPROC
8#define CFI_ENDPROC 8#define CFI_ENDPROC
9#define CFI_REMEMBER_STATE
10#define CFI_RESTORE_STATE
9 11
10#endif /* PERF_DWARF2_H */ 12#endif /* PERF_DWARF2_H */
11 13
diff --git a/tools/perf/util/include/linux/bitmap.h b/tools/perf/util/include/linux/bitmap.h
index eda4416efa0a..bb162e40c76c 100644
--- a/tools/perf/util/include/linux/bitmap.h
+++ b/tools/perf/util/include/linux/bitmap.h
@@ -5,6 +5,8 @@
5#include <linux/bitops.h> 5#include <linux/bitops.h>
6 6
7int __bitmap_weight(const unsigned long *bitmap, int bits); 7int __bitmap_weight(const unsigned long *bitmap, int bits);
8void __bitmap_or(unsigned long *dst, const unsigned long *bitmap1,
9 const unsigned long *bitmap2, int bits);
8 10
9#define BITMAP_LAST_WORD_MASK(nbits) \ 11#define BITMAP_LAST_WORD_MASK(nbits) \
10( \ 12( \
@@ -32,4 +34,13 @@ static inline int bitmap_weight(const unsigned long *src, int nbits)
32 return __bitmap_weight(src, nbits); 34 return __bitmap_weight(src, nbits);
33} 35}
34 36
37static inline void bitmap_or(unsigned long *dst, const unsigned long *src1,
38 const unsigned long *src2, int nbits)
39{
40 if (small_const_nbits(nbits))
41 *dst = *src1 | *src2;
42 else
43 __bitmap_or(dst, src1, src2, nbits);
44}
45
35#endif /* _PERF_BITOPS_H */ 46#endif /* _PERF_BITOPS_H */
diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c
index 316aa0ab7122..dea6d1c1a954 100644
--- a/tools/perf/util/map.c
+++ b/tools/perf/util/map.c
@@ -212,6 +212,21 @@ size_t map__fprintf(struct map *self, FILE *fp)
212 self->start, self->end, self->pgoff, self->dso->name); 212 self->start, self->end, self->pgoff, self->dso->name);
213} 213}
214 214
215size_t map__fprintf_dsoname(struct map *map, FILE *fp)
216{
217 const char *dsoname;
218
219 if (map && map->dso && (map->dso->name || map->dso->long_name)) {
220 if (symbol_conf.show_kernel_path && map->dso->long_name)
221 dsoname = map->dso->long_name;
222 else if (map->dso->name)
223 dsoname = map->dso->name;
224 } else
225 dsoname = "[unknown]";
226
227 return fprintf(fp, "%s", dsoname);
228}
229
215/* 230/*
216 * objdump wants/reports absolute IPs for ET_EXEC, and RIPs for ET_DYN. 231 * objdump wants/reports absolute IPs for ET_EXEC, and RIPs for ET_DYN.
217 * map->dso->adjust_symbols==1 for ET_EXEC-like cases. 232 * map->dso->adjust_symbols==1 for ET_EXEC-like cases.
diff --git a/tools/perf/util/map.h b/tools/perf/util/map.h
index 2b8017f8a930..b100c20b7f94 100644
--- a/tools/perf/util/map.h
+++ b/tools/perf/util/map.h
@@ -118,6 +118,7 @@ void map__delete(struct map *self);
118struct map *map__clone(struct map *self); 118struct map *map__clone(struct map *self);
119int map__overlap(struct map *l, struct map *r); 119int map__overlap(struct map *l, struct map *r);
120size_t map__fprintf(struct map *self, FILE *fp); 120size_t map__fprintf(struct map *self, FILE *fp);
121size_t map__fprintf_dsoname(struct map *map, FILE *fp);
121 122
122int map__load(struct map *self, symbol_filter_t filter); 123int map__load(struct map *self, symbol_filter_t filter);
123struct symbol *map__find_symbol(struct map *self, 124struct symbol *map__find_symbol(struct map *self,
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index e33554a562b3..8a8ee64e72d1 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -34,7 +34,6 @@
34 34
35#include "util.h" 35#include "util.h"
36#include "event.h" 36#include "event.h"
37#include "string.h"
38#include "strlist.h" 37#include "strlist.h"
39#include "debug.h" 38#include "debug.h"
40#include "cache.h" 39#include "cache.h"
@@ -273,10 +272,10 @@ static int add_module_to_probe_trace_events(struct probe_trace_event *tevs,
273/* Try to find perf_probe_event with debuginfo */ 272/* Try to find perf_probe_event with debuginfo */
274static int try_to_find_probe_trace_events(struct perf_probe_event *pev, 273static int try_to_find_probe_trace_events(struct perf_probe_event *pev,
275 struct probe_trace_event **tevs, 274 struct probe_trace_event **tevs,
276 int max_tevs, const char *module) 275 int max_tevs, const char *target)
277{ 276{
278 bool need_dwarf = perf_probe_event_need_dwarf(pev); 277 bool need_dwarf = perf_probe_event_need_dwarf(pev);
279 struct debuginfo *dinfo = open_debuginfo(module); 278 struct debuginfo *dinfo = open_debuginfo(target);
280 int ntevs, ret = 0; 279 int ntevs, ret = 0;
281 280
282 if (!dinfo) { 281 if (!dinfo) {
@@ -295,9 +294,9 @@ static int try_to_find_probe_trace_events(struct perf_probe_event *pev,
295 294
296 if (ntevs > 0) { /* Succeeded to find trace events */ 295 if (ntevs > 0) { /* Succeeded to find trace events */
297 pr_debug("find %d probe_trace_events.\n", ntevs); 296 pr_debug("find %d probe_trace_events.\n", ntevs);
298 if (module) 297 if (target)
299 ret = add_module_to_probe_trace_events(*tevs, ntevs, 298 ret = add_module_to_probe_trace_events(*tevs, ntevs,
300 module); 299 target);
301 return ret < 0 ? ret : ntevs; 300 return ret < 0 ? ret : ntevs;
302 } 301 }
303 302
@@ -1729,7 +1728,7 @@ static int __add_probe_trace_events(struct perf_probe_event *pev,
1729 } 1728 }
1730 1729
1731 ret = 0; 1730 ret = 0;
1732 printf("Add new event%s\n", (ntevs > 1) ? "s:" : ":"); 1731 printf("Added new event%s\n", (ntevs > 1) ? "s:" : ":");
1733 for (i = 0; i < ntevs; i++) { 1732 for (i = 0; i < ntevs; i++) {
1734 tev = &tevs[i]; 1733 tev = &tevs[i];
1735 if (pev->event) 1734 if (pev->event)
@@ -1784,7 +1783,7 @@ static int __add_probe_trace_events(struct perf_probe_event *pev,
1784 1783
1785 if (ret >= 0) { 1784 if (ret >= 0) {
1786 /* Show how to use the event. */ 1785 /* Show how to use the event. */
1787 printf("\nYou can now use it on all perf tools, such as:\n\n"); 1786 printf("\nYou can now use it in all perf tools, such as:\n\n");
1788 printf("\tperf record -e %s:%s -aR sleep 1\n\n", tev->group, 1787 printf("\tperf record -e %s:%s -aR sleep 1\n\n", tev->group,
1789 tev->event); 1788 tev->event);
1790 } 1789 }
@@ -1796,14 +1795,14 @@ static int __add_probe_trace_events(struct perf_probe_event *pev,
1796 1795
1797static int convert_to_probe_trace_events(struct perf_probe_event *pev, 1796static int convert_to_probe_trace_events(struct perf_probe_event *pev,
1798 struct probe_trace_event **tevs, 1797 struct probe_trace_event **tevs,
1799 int max_tevs, const char *module) 1798 int max_tevs, const char *target)
1800{ 1799{
1801 struct symbol *sym; 1800 struct symbol *sym;
1802 int ret = 0, i; 1801 int ret = 0, i;
1803 struct probe_trace_event *tev; 1802 struct probe_trace_event *tev;
1804 1803
1805 /* Convert perf_probe_event with debuginfo */ 1804 /* Convert perf_probe_event with debuginfo */
1806 ret = try_to_find_probe_trace_events(pev, tevs, max_tevs, module); 1805 ret = try_to_find_probe_trace_events(pev, tevs, max_tevs, target);
1807 if (ret != 0) 1806 if (ret != 0)
1808 return ret; /* Found in debuginfo or got an error */ 1807 return ret; /* Found in debuginfo or got an error */
1809 1808
@@ -1819,8 +1818,8 @@ static int convert_to_probe_trace_events(struct perf_probe_event *pev,
1819 goto error; 1818 goto error;
1820 } 1819 }
1821 1820
1822 if (module) { 1821 if (target) {
1823 tev->point.module = strdup(module); 1822 tev->point.module = strdup(target);
1824 if (tev->point.module == NULL) { 1823 if (tev->point.module == NULL) {
1825 ret = -ENOMEM; 1824 ret = -ENOMEM;
1826 goto error; 1825 goto error;
@@ -1890,7 +1889,7 @@ struct __event_package {
1890}; 1889};
1891 1890
1892int add_perf_probe_events(struct perf_probe_event *pevs, int npevs, 1891int add_perf_probe_events(struct perf_probe_event *pevs, int npevs,
1893 int max_tevs, const char *module, bool force_add) 1892 int max_tevs, const char *target, bool force_add)
1894{ 1893{
1895 int i, j, ret; 1894 int i, j, ret;
1896 struct __event_package *pkgs; 1895 struct __event_package *pkgs;
@@ -1913,7 +1912,7 @@ int add_perf_probe_events(struct perf_probe_event *pevs, int npevs,
1913 ret = convert_to_probe_trace_events(pkgs[i].pev, 1912 ret = convert_to_probe_trace_events(pkgs[i].pev,
1914 &pkgs[i].tevs, 1913 &pkgs[i].tevs,
1915 max_tevs, 1914 max_tevs,
1916 module); 1915 target);
1917 if (ret < 0) 1916 if (ret < 0)
1918 goto end; 1917 goto end;
1919 pkgs[i].ntevs = ret; 1918 pkgs[i].ntevs = ret;
@@ -1965,7 +1964,7 @@ static int __del_trace_probe_event(int fd, struct str_node *ent)
1965 goto error; 1964 goto error;
1966 } 1965 }
1967 1966
1968 printf("Remove event: %s\n", ent->s); 1967 printf("Removed event: %s\n", ent->s);
1969 return 0; 1968 return 0;
1970error: 1969error:
1971 pr_warning("Failed to delete event: %s\n", strerror(-ret)); 1970 pr_warning("Failed to delete event: %s\n", strerror(-ret));
@@ -2069,7 +2068,7 @@ static int filter_available_functions(struct map *map __unused,
2069 return 1; 2068 return 1;
2070} 2069}
2071 2070
2072int show_available_funcs(const char *module, struct strfilter *_filter) 2071int show_available_funcs(const char *target, struct strfilter *_filter)
2073{ 2072{
2074 struct map *map; 2073 struct map *map;
2075 int ret; 2074 int ret;
@@ -2080,9 +2079,9 @@ int show_available_funcs(const char *module, struct strfilter *_filter)
2080 if (ret < 0) 2079 if (ret < 0)
2081 return ret; 2080 return ret;
2082 2081
2083 map = kernel_get_module_map(module); 2082 map = kernel_get_module_map(target);
2084 if (!map) { 2083 if (!map) {
2085 pr_err("Failed to find %s map.\n", (module) ? : "kernel"); 2084 pr_err("Failed to find %s map.\n", (target) ? : "kernel");
2086 return -EINVAL; 2085 return -EINVAL;
2087 } 2086 }
2088 available_func_filter = _filter; 2087 available_func_filter = _filter;
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c
index 74bd2e63c4b4..2cc162d3b78c 100644
--- a/tools/perf/util/probe-finder.c
+++ b/tools/perf/util/probe-finder.c
@@ -30,7 +30,6 @@
30#include <stdlib.h> 30#include <stdlib.h>
31#include <string.h> 31#include <string.h>
32#include <stdarg.h> 32#include <stdarg.h>
33#include <ctype.h>
34#include <dwarf-regs.h> 33#include <dwarf-regs.h>
35 34
36#include <linux/bitops.h> 35#include <linux/bitops.h>
diff --git a/tools/perf/util/python-ext-sources b/tools/perf/util/python-ext-sources
new file mode 100644
index 000000000000..2884e67ee625
--- /dev/null
+++ b/tools/perf/util/python-ext-sources
@@ -0,0 +1,19 @@
1#
2# List of files needed by perf python extention
3#
4# Each source file must be placed on its own line so that it can be
5# processed by Makefile and util/setup.py accordingly.
6#
7
8util/python.c
9util/ctype.c
10util/evlist.c
11util/evsel.c
12util/cpumap.c
13util/thread_map.c
14util/util.c
15util/xyarray.c
16util/cgroup.c
17util/debugfs.c
18util/strlist.c
19../../lib/rbtree.c
diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c
index 9dd47a4f2596..e03b58a48424 100644
--- a/tools/perf/util/python.c
+++ b/tools/perf/util/python.c
@@ -425,14 +425,14 @@ struct pyrf_thread_map {
425static int pyrf_thread_map__init(struct pyrf_thread_map *pthreads, 425static int pyrf_thread_map__init(struct pyrf_thread_map *pthreads,
426 PyObject *args, PyObject *kwargs) 426 PyObject *args, PyObject *kwargs)
427{ 427{
428 static char *kwlist[] = { "pid", "tid", NULL }; 428 static char *kwlist[] = { "pid", "tid", "uid", NULL };
429 int pid = -1, tid = -1; 429 int pid = -1, tid = -1, uid = UINT_MAX;
430 430
431 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|ii", 431 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iii",
432 kwlist, &pid, &tid)) 432 kwlist, &pid, &tid, &uid))
433 return -1; 433 return -1;
434 434
435 pthreads->threads = thread_map__new(pid, tid); 435 pthreads->threads = thread_map__new(pid, tid, uid);
436 if (pthreads->threads == NULL) 436 if (pthreads->threads == NULL)
437 return -1; 437 return -1;
438 return 0; 438 return 0;
diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c
index 0b2a48783172..c2623c6f9b51 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -24,7 +24,6 @@
24#include <stdio.h> 24#include <stdio.h>
25#include <stdlib.h> 25#include <stdlib.h>
26#include <string.h> 26#include <string.h>
27#include <ctype.h>
28#include <errno.h> 27#include <errno.h>
29 28
30#include "../../perf.h" 29#include "../../perf.h"
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index b5ca2558c7bb..9f833cf9c6a9 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -796,6 +796,10 @@ static int perf_session_deliver_event(struct perf_session *session,
796 ++session->hists.stats.nr_unknown_id; 796 ++session->hists.stats.nr_unknown_id;
797 return -1; 797 return -1;
798 } 798 }
799 if (machine == NULL) {
800 ++session->hists.stats.nr_unprocessable_samples;
801 return -1;
802 }
799 return tool->sample(tool, event, sample, evsel, machine); 803 return tool->sample(tool, event, sample, evsel, machine);
800 case PERF_RECORD_MMAP: 804 case PERF_RECORD_MMAP:
801 return tool->mmap(tool, event, sample, machine); 805 return tool->mmap(tool, event, sample, machine);
@@ -964,6 +968,12 @@ static void perf_session__warn_about_errors(const struct perf_session *session,
964 session->hists.stats.nr_invalid_chains, 968 session->hists.stats.nr_invalid_chains,
965 session->hists.stats.nr_events[PERF_RECORD_SAMPLE]); 969 session->hists.stats.nr_events[PERF_RECORD_SAMPLE]);
966 } 970 }
971
972 if (session->hists.stats.nr_unprocessable_samples != 0) {
973 ui__warning("%u unprocessable samples recorded.\n"
974 "Do you have a KVM guest running and not using 'perf kvm'?\n",
975 session->hists.stats.nr_unprocessable_samples);
976 }
967} 977}
968 978
969#define session_done() (*(volatile int *)(&session_done)) 979#define session_done() (*(volatile int *)(&session_done))
@@ -1293,10 +1303,9 @@ struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session,
1293 1303
1294void perf_event__print_ip(union perf_event *event, struct perf_sample *sample, 1304void perf_event__print_ip(union perf_event *event, struct perf_sample *sample,
1295 struct machine *machine, struct perf_evsel *evsel, 1305 struct machine *machine, struct perf_evsel *evsel,
1296 int print_sym, int print_dso) 1306 int print_sym, int print_dso, int print_symoffset)
1297{ 1307{
1298 struct addr_location al; 1308 struct addr_location al;
1299 const char *symname, *dsoname;
1300 struct callchain_cursor *cursor = &evsel->hists.callchain_cursor; 1309 struct callchain_cursor *cursor = &evsel->hists.callchain_cursor;
1301 struct callchain_cursor_node *node; 1310 struct callchain_cursor_node *node;
1302 1311
@@ -1324,20 +1333,13 @@ void perf_event__print_ip(union perf_event *event, struct perf_sample *sample,
1324 1333
1325 printf("\t%16" PRIx64, node->ip); 1334 printf("\t%16" PRIx64, node->ip);
1326 if (print_sym) { 1335 if (print_sym) {
1327 if (node->sym && node->sym->name) 1336 printf(" ");
1328 symname = node->sym->name; 1337 symbol__fprintf_symname(node->sym, stdout);
1329 else
1330 symname = "";
1331
1332 printf(" %s", symname);
1333 } 1338 }
1334 if (print_dso) { 1339 if (print_dso) {
1335 if (node->map && node->map->dso && node->map->dso->name) 1340 printf(" (");
1336 dsoname = node->map->dso->name; 1341 map__fprintf_dsoname(al.map, stdout);
1337 else 1342 printf(")");
1338 dsoname = "";
1339
1340 printf(" (%s)", dsoname);
1341 } 1343 }
1342 printf("\n"); 1344 printf("\n");
1343 1345
@@ -1347,21 +1349,18 @@ void perf_event__print_ip(union perf_event *event, struct perf_sample *sample,
1347 } else { 1349 } else {
1348 printf("%16" PRIx64, sample->ip); 1350 printf("%16" PRIx64, sample->ip);
1349 if (print_sym) { 1351 if (print_sym) {
1350 if (al.sym && al.sym->name) 1352 printf(" ");
1351 symname = al.sym->name; 1353 if (print_symoffset)
1354 symbol__fprintf_symname_offs(al.sym, &al,
1355 stdout);
1352 else 1356 else
1353 symname = ""; 1357 symbol__fprintf_symname(al.sym, stdout);
1354
1355 printf(" %s", symname);
1356 } 1358 }
1357 1359
1358 if (print_dso) { 1360 if (print_dso) {
1359 if (al.map && al.map->dso && al.map->dso->name) 1361 printf(" (");
1360 dsoname = al.map->dso->name; 1362 map__fprintf_dsoname(al.map, stdout);
1361 else 1363 printf(")");
1362 dsoname = "";
1363
1364 printf(" (%s)", dsoname);
1365 } 1364 }
1366 } 1365 }
1367} 1366}
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h
index 37bc38381fb6..c8d90178e7de 100644
--- a/tools/perf/util/session.h
+++ b/tools/perf/util/session.h
@@ -147,7 +147,7 @@ struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session,
147 147
148void perf_event__print_ip(union perf_event *event, struct perf_sample *sample, 148void perf_event__print_ip(union perf_event *event, struct perf_sample *sample,
149 struct machine *machine, struct perf_evsel *evsel, 149 struct machine *machine, struct perf_evsel *evsel,
150 int print_sym, int print_dso); 150 int print_sym, int print_dso, int print_symoffset);
151 151
152int perf_session__cpu_bitmap(struct perf_session *session, 152int perf_session__cpu_bitmap(struct perf_session *session,
153 const char *cpu_list, unsigned long *cpu_bitmap); 153 const char *cpu_list, unsigned long *cpu_bitmap);
diff --git a/tools/perf/util/setup.py b/tools/perf/util/setup.py
index 36d4c5619575..d0f9f29cf181 100644
--- a/tools/perf/util/setup.py
+++ b/tools/perf/util/setup.py
@@ -24,11 +24,11 @@ cflags += getenv('CFLAGS', '').split()
24build_lib = getenv('PYTHON_EXTBUILD_LIB') 24build_lib = getenv('PYTHON_EXTBUILD_LIB')
25build_tmp = getenv('PYTHON_EXTBUILD_TMP') 25build_tmp = getenv('PYTHON_EXTBUILD_TMP')
26 26
27ext_sources = [f.strip() for f in file('util/python-ext-sources')
28 if len(f.strip()) > 0 and f[0] != '#']
29
27perf = Extension('perf', 30perf = Extension('perf',
28 sources = ['util/python.c', 'util/ctype.c', 'util/evlist.c', 31 sources = ext_sources,
29 'util/evsel.c', 'util/cpumap.c', 'util/thread_map.c',
30 'util/util.c', 'util/xyarray.c', 'util/cgroup.c',
31 'util/debugfs.c'],
32 include_dirs = ['util/include'], 32 include_dirs = ['util/include'],
33 extra_compile_args = cflags, 33 extra_compile_args = cflags,
34 ) 34 )
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index 0975438c3e72..5dd83c3e2c0c 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -1,4 +1,3 @@
1#include <ctype.h>
2#include <dirent.h> 1#include <dirent.h>
3#include <errno.h> 2#include <errno.h>
4#include <libgen.h> 3#include <libgen.h>
@@ -12,6 +11,7 @@
12#include <unistd.h> 11#include <unistd.h>
13#include <inttypes.h> 12#include <inttypes.h>
14#include "build-id.h" 13#include "build-id.h"
14#include "util.h"
15#include "debug.h" 15#include "debug.h"
16#include "symbol.h" 16#include "symbol.h"
17#include "strlist.h" 17#include "strlist.h"
@@ -263,6 +263,28 @@ static size_t symbol__fprintf(struct symbol *sym, FILE *fp)
263 sym->name); 263 sym->name);
264} 264}
265 265
266size_t symbol__fprintf_symname_offs(const struct symbol *sym,
267 const struct addr_location *al, FILE *fp)
268{
269 unsigned long offset;
270 size_t length;
271
272 if (sym && sym->name) {
273 length = fprintf(fp, "%s", sym->name);
274 if (al) {
275 offset = al->addr - sym->start;
276 length += fprintf(fp, "+0x%lx", offset);
277 }
278 return length;
279 } else
280 return fprintf(fp, "[unknown]");
281}
282
283size_t symbol__fprintf_symname(const struct symbol *sym, FILE *fp)
284{
285 return symbol__fprintf_symname_offs(sym, NULL, fp);
286}
287
266void dso__set_long_name(struct dso *dso, char *name) 288void dso__set_long_name(struct dso *dso, char *name)
267{ 289{
268 if (name == NULL) 290 if (name == NULL)
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index 123c2e14353e..2a683d4fc918 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -70,6 +70,7 @@ struct symbol_conf {
70 unsigned short priv_size; 70 unsigned short priv_size;
71 unsigned short nr_events; 71 unsigned short nr_events;
72 bool try_vmlinux_path, 72 bool try_vmlinux_path,
73 show_kernel_path,
73 use_modules, 74 use_modules,
74 sort_by_name, 75 sort_by_name,
75 show_nr_samples, 76 show_nr_samples,
@@ -241,6 +242,9 @@ void machines__destroy_guest_kernel_maps(struct rb_root *machines);
241 242
242int symbol__init(void); 243int symbol__init(void);
243void symbol__exit(void); 244void symbol__exit(void);
245size_t symbol__fprintf_symname_offs(const struct symbol *sym,
246 const struct addr_location *al, FILE *fp);
247size_t symbol__fprintf_symname(const struct symbol *sym, FILE *fp);
244bool symbol_type__is_a(char symbol_type, enum map_type map_type); 248bool symbol_type__is_a(char symbol_type, enum map_type map_type);
245 249
246size_t machine__fprintf_vmlinux_path(struct machine *machine, FILE *fp); 250size_t machine__fprintf_vmlinux_path(struct machine *machine, FILE *fp);
diff --git a/tools/perf/util/sysfs.c b/tools/perf/util/sysfs.c
new file mode 100644
index 000000000000..48c6902e749f
--- /dev/null
+++ b/tools/perf/util/sysfs.c
@@ -0,0 +1,60 @@
1
2#include "util.h"
3#include "sysfs.h"
4
5static const char * const sysfs_known_mountpoints[] = {
6 "/sys",
7 0,
8};
9
10static int sysfs_found;
11char sysfs_mountpoint[PATH_MAX];
12
13static int sysfs_valid_mountpoint(const char *sysfs)
14{
15 struct statfs st_fs;
16
17 if (statfs(sysfs, &st_fs) < 0)
18 return -ENOENT;
19 else if (st_fs.f_type != (long) SYSFS_MAGIC)
20 return -ENOENT;
21
22 return 0;
23}
24
25const char *sysfs_find_mountpoint(void)
26{
27 const char * const *ptr;
28 char type[100];
29 FILE *fp;
30
31 if (sysfs_found)
32 return (const char *) sysfs_mountpoint;
33
34 ptr = sysfs_known_mountpoints;
35 while (*ptr) {
36 if (sysfs_valid_mountpoint(*ptr) == 0) {
37 sysfs_found = 1;
38 strcpy(sysfs_mountpoint, *ptr);
39 return sysfs_mountpoint;
40 }
41 ptr++;
42 }
43
44 /* give up and parse /proc/mounts */
45 fp = fopen("/proc/mounts", "r");
46 if (fp == NULL)
47 return NULL;
48
49 while (!sysfs_found &&
50 fscanf(fp, "%*s %" STR(PATH_MAX) "s %99s %*s %*d %*d\n",
51 sysfs_mountpoint, type) == 2) {
52
53 if (strcmp(type, "sysfs") == 0)
54 sysfs_found = 1;
55 }
56
57 fclose(fp);
58
59 return sysfs_found ? sysfs_mountpoint : NULL;
60}
diff --git a/tools/perf/util/sysfs.h b/tools/perf/util/sysfs.h
new file mode 100644
index 000000000000..a813b7203938
--- /dev/null
+++ b/tools/perf/util/sysfs.h
@@ -0,0 +1,6 @@
1#ifndef __SYSFS_H__
2#define __SYSFS_H__
3
4const char *sysfs_find_mountpoint(void);
5
6#endif /* __DEBUGFS_H__ */
diff --git a/tools/perf/util/thread_map.c b/tools/perf/util/thread_map.c
index a5df131b77c3..84d9bd782004 100644
--- a/tools/perf/util/thread_map.c
+++ b/tools/perf/util/thread_map.c
@@ -1,6 +1,13 @@
1#include <dirent.h> 1#include <dirent.h>
2#include <limits.h>
3#include <stdbool.h>
2#include <stdlib.h> 4#include <stdlib.h>
3#include <stdio.h> 5#include <stdio.h>
6#include <sys/types.h>
7#include <sys/stat.h>
8#include <unistd.h>
9#include "strlist.h"
10#include <string.h>
4#include "thread_map.h" 11#include "thread_map.h"
5 12
6/* Skip "." and ".." directories */ 13/* Skip "." and ".." directories */
@@ -23,7 +30,7 @@ struct thread_map *thread_map__new_by_pid(pid_t pid)
23 sprintf(name, "/proc/%d/task", pid); 30 sprintf(name, "/proc/%d/task", pid);
24 items = scandir(name, &namelist, filter, NULL); 31 items = scandir(name, &namelist, filter, NULL);
25 if (items <= 0) 32 if (items <= 0)
26 return NULL; 33 return NULL;
27 34
28 threads = malloc(sizeof(*threads) + sizeof(pid_t) * items); 35 threads = malloc(sizeof(*threads) + sizeof(pid_t) * items);
29 if (threads != NULL) { 36 if (threads != NULL) {
@@ -51,14 +58,240 @@ struct thread_map *thread_map__new_by_tid(pid_t tid)
51 return threads; 58 return threads;
52} 59}
53 60
54struct thread_map *thread_map__new(pid_t pid, pid_t tid) 61struct thread_map *thread_map__new_by_uid(uid_t uid)
62{
63 DIR *proc;
64 int max_threads = 32, items, i;
65 char path[256];
66 struct dirent dirent, *next, **namelist = NULL;
67 struct thread_map *threads = malloc(sizeof(*threads) +
68 max_threads * sizeof(pid_t));
69 if (threads == NULL)
70 goto out;
71
72 proc = opendir("/proc");
73 if (proc == NULL)
74 goto out_free_threads;
75
76 threads->nr = 0;
77
78 while (!readdir_r(proc, &dirent, &next) && next) {
79 char *end;
80 bool grow = false;
81 struct stat st;
82 pid_t pid = strtol(dirent.d_name, &end, 10);
83
84 if (*end) /* only interested in proper numerical dirents */
85 continue;
86
87 snprintf(path, sizeof(path), "/proc/%s", dirent.d_name);
88
89 if (stat(path, &st) != 0)
90 continue;
91
92 if (st.st_uid != uid)
93 continue;
94
95 snprintf(path, sizeof(path), "/proc/%d/task", pid);
96 items = scandir(path, &namelist, filter, NULL);
97 if (items <= 0)
98 goto out_free_closedir;
99
100 while (threads->nr + items >= max_threads) {
101 max_threads *= 2;
102 grow = true;
103 }
104
105 if (grow) {
106 struct thread_map *tmp;
107
108 tmp = realloc(threads, (sizeof(*threads) +
109 max_threads * sizeof(pid_t)));
110 if (tmp == NULL)
111 goto out_free_namelist;
112
113 threads = tmp;
114 }
115
116 for (i = 0; i < items; i++)
117 threads->map[threads->nr + i] = atoi(namelist[i]->d_name);
118
119 for (i = 0; i < items; i++)
120 free(namelist[i]);
121 free(namelist);
122
123 threads->nr += items;
124 }
125
126out_closedir:
127 closedir(proc);
128out:
129 return threads;
130
131out_free_threads:
132 free(threads);
133 return NULL;
134
135out_free_namelist:
136 for (i = 0; i < items; i++)
137 free(namelist[i]);
138 free(namelist);
139
140out_free_closedir:
141 free(threads);
142 threads = NULL;
143 goto out_closedir;
144}
145
146struct thread_map *thread_map__new(pid_t pid, pid_t tid, uid_t uid)
55{ 147{
56 if (pid != -1) 148 if (pid != -1)
57 return thread_map__new_by_pid(pid); 149 return thread_map__new_by_pid(pid);
150
151 if (tid == -1 && uid != UINT_MAX)
152 return thread_map__new_by_uid(uid);
153
58 return thread_map__new_by_tid(tid); 154 return thread_map__new_by_tid(tid);
59} 155}
60 156
157static struct thread_map *thread_map__new_by_pid_str(const char *pid_str)
158{
159 struct thread_map *threads = NULL, *nt;
160 char name[256];
161 int items, total_tasks = 0;
162 struct dirent **namelist = NULL;
163 int i, j = 0;
164 pid_t pid, prev_pid = INT_MAX;
165 char *end_ptr;
166 struct str_node *pos;
167 struct strlist *slist = strlist__new(false, pid_str);
168
169 if (!slist)
170 return NULL;
171
172 strlist__for_each(pos, slist) {
173 pid = strtol(pos->s, &end_ptr, 10);
174
175 if (pid == INT_MIN || pid == INT_MAX ||
176 (*end_ptr != '\0' && *end_ptr != ','))
177 goto out_free_threads;
178
179 if (pid == prev_pid)
180 continue;
181
182 sprintf(name, "/proc/%d/task", pid);
183 items = scandir(name, &namelist, filter, NULL);
184 if (items <= 0)
185 goto out_free_threads;
186
187 total_tasks += items;
188 nt = realloc(threads, (sizeof(*threads) +
189 sizeof(pid_t) * total_tasks));
190 if (nt == NULL)
191 goto out_free_threads;
192
193 threads = nt;
194
195 if (threads) {
196 for (i = 0; i < items; i++)
197 threads->map[j++] = atoi(namelist[i]->d_name);
198 threads->nr = total_tasks;
199 }
200
201 for (i = 0; i < items; i++)
202 free(namelist[i]);
203 free(namelist);
204
205 if (!threads)
206 break;
207 }
208
209out:
210 strlist__delete(slist);
211 return threads;
212
213out_free_threads:
214 free(threads);
215 threads = NULL;
216 goto out;
217}
218
219static struct thread_map *thread_map__new_by_tid_str(const char *tid_str)
220{
221 struct thread_map *threads = NULL, *nt;
222 int ntasks = 0;
223 pid_t tid, prev_tid = INT_MAX;
224 char *end_ptr;
225 struct str_node *pos;
226 struct strlist *slist;
227
228 /* perf-stat expects threads to be generated even if tid not given */
229 if (!tid_str) {
230 threads = malloc(sizeof(*threads) + sizeof(pid_t));
231 if (threads != NULL) {
232 threads->map[0] = -1;
233 threads->nr = 1;
234 }
235 return threads;
236 }
237
238 slist = strlist__new(false, tid_str);
239 if (!slist)
240 return NULL;
241
242 strlist__for_each(pos, slist) {
243 tid = strtol(pos->s, &end_ptr, 10);
244
245 if (tid == INT_MIN || tid == INT_MAX ||
246 (*end_ptr != '\0' && *end_ptr != ','))
247 goto out_free_threads;
248
249 if (tid == prev_tid)
250 continue;
251
252 ntasks++;
253 nt = realloc(threads, sizeof(*threads) + sizeof(pid_t) * ntasks);
254
255 if (nt == NULL)
256 goto out_free_threads;
257
258 threads = nt;
259 threads->map[ntasks - 1] = tid;
260 threads->nr = ntasks;
261 }
262out:
263 return threads;
264
265out_free_threads:
266 free(threads);
267 threads = NULL;
268 goto out;
269}
270
271struct thread_map *thread_map__new_str(const char *pid, const char *tid,
272 uid_t uid)
273{
274 if (pid)
275 return thread_map__new_by_pid_str(pid);
276
277 if (!tid && uid != UINT_MAX)
278 return thread_map__new_by_uid(uid);
279
280 return thread_map__new_by_tid_str(tid);
281}
282
61void thread_map__delete(struct thread_map *threads) 283void thread_map__delete(struct thread_map *threads)
62{ 284{
63 free(threads); 285 free(threads);
64} 286}
287
288size_t thread_map__fprintf(struct thread_map *threads, FILE *fp)
289{
290 int i;
291 size_t printed = fprintf(fp, "%d thread%s: ",
292 threads->nr, threads->nr > 1 ? "s" : "");
293 for (i = 0; i < threads->nr; ++i)
294 printed += fprintf(fp, "%s%d", i ? ", " : "", threads->map[i]);
295
296 return printed + fprintf(fp, "\n");
297}
diff --git a/tools/perf/util/thread_map.h b/tools/perf/util/thread_map.h
index 3cb907311409..7da80f14418b 100644
--- a/tools/perf/util/thread_map.h
+++ b/tools/perf/util/thread_map.h
@@ -2,6 +2,7 @@
2#define __PERF_THREAD_MAP_H 2#define __PERF_THREAD_MAP_H
3 3
4#include <sys/types.h> 4#include <sys/types.h>
5#include <stdio.h>
5 6
6struct thread_map { 7struct thread_map {
7 int nr; 8 int nr;
@@ -10,6 +11,14 @@ struct thread_map {
10 11
11struct thread_map *thread_map__new_by_pid(pid_t pid); 12struct thread_map *thread_map__new_by_pid(pid_t pid);
12struct thread_map *thread_map__new_by_tid(pid_t tid); 13struct thread_map *thread_map__new_by_tid(pid_t tid);
13struct thread_map *thread_map__new(pid_t pid, pid_t tid); 14struct thread_map *thread_map__new_by_uid(uid_t uid);
15struct thread_map *thread_map__new(pid_t pid, pid_t tid, uid_t uid);
16
17struct thread_map *thread_map__new_str(const char *pid,
18 const char *tid, uid_t uid);
19
14void thread_map__delete(struct thread_map *threads); 20void thread_map__delete(struct thread_map *threads);
21
22size_t thread_map__fprintf(struct thread_map *threads, FILE *fp);
23
15#endif /* __PERF_THREAD_MAP_H */ 24#endif /* __PERF_THREAD_MAP_H */
diff --git a/tools/perf/util/top.c b/tools/perf/util/top.c
index 500471dffa4f..09fe579ccafb 100644
--- a/tools/perf/util/top.c
+++ b/tools/perf/util/top.c
@@ -69,12 +69,15 @@ size_t perf_top__header_snprintf(struct perf_top *top, char *bf, size_t size)
69 69
70 ret += SNPRINTF(bf + ret, size - ret, "], "); 70 ret += SNPRINTF(bf + ret, size - ret, "], ");
71 71
72 if (top->target_pid != -1) 72 if (top->target_pid)
73 ret += SNPRINTF(bf + ret, size - ret, " (target_pid: %d", 73 ret += SNPRINTF(bf + ret, size - ret, " (target_pid: %s",
74 top->target_pid); 74 top->target_pid);
75 else if (top->target_tid != -1) 75 else if (top->target_tid)
76 ret += SNPRINTF(bf + ret, size - ret, " (target_tid: %d", 76 ret += SNPRINTF(bf + ret, size - ret, " (target_tid: %s",
77 top->target_tid); 77 top->target_tid);
78 else if (top->uid_str != NULL)
79 ret += SNPRINTF(bf + ret, size - ret, " (uid: %s",
80 top->uid_str);
78 else 81 else
79 ret += SNPRINTF(bf + ret, size - ret, " (all"); 82 ret += SNPRINTF(bf + ret, size - ret, " (all");
80 83
@@ -82,7 +85,7 @@ size_t perf_top__header_snprintf(struct perf_top *top, char *bf, size_t size)
82 ret += SNPRINTF(bf + ret, size - ret, ", CPU%s: %s)", 85 ret += SNPRINTF(bf + ret, size - ret, ", CPU%s: %s)",
83 top->evlist->cpus->nr > 1 ? "s" : "", top->cpu_list); 86 top->evlist->cpus->nr > 1 ? "s" : "", top->cpu_list);
84 else { 87 else {
85 if (top->target_tid != -1) 88 if (top->target_tid)
86 ret += SNPRINTF(bf + ret, size - ret, ")"); 89 ret += SNPRINTF(bf + ret, size - ret, ")");
87 else 90 else
88 ret += SNPRINTF(bf + ret, size - ret, ", %d CPU%s)", 91 ret += SNPRINTF(bf + ret, size - ret, ", %d CPU%s)",
diff --git a/tools/perf/util/top.h b/tools/perf/util/top.h
index f2eab81435ae..ce61cb2d1acf 100644
--- a/tools/perf/util/top.h
+++ b/tools/perf/util/top.h
@@ -23,7 +23,8 @@ struct perf_top {
23 u64 guest_us_samples, guest_kernel_samples; 23 u64 guest_us_samples, guest_kernel_samples;
24 int print_entries, count_filter, delay_secs; 24 int print_entries, count_filter, delay_secs;
25 int freq; 25 int freq;
26 pid_t target_pid, target_tid; 26 const char *target_pid, *target_tid;
27 uid_t uid;
27 bool hide_kernel_symbols, hide_user_symbols, zero; 28 bool hide_kernel_symbols, hide_user_symbols, zero;
28 bool system_wide; 29 bool system_wide;
29 bool use_tui, use_stdio; 30 bool use_tui, use_stdio;
@@ -33,7 +34,7 @@ struct perf_top {
33 bool vmlinux_warned; 34 bool vmlinux_warned;
34 bool inherit; 35 bool inherit;
35 bool group; 36 bool group;
36 bool sample_id_all_avail; 37 bool sample_id_all_missing;
37 bool exclude_guest_missing; 38 bool exclude_guest_missing;
38 bool dump_symtab; 39 bool dump_symtab;
39 const char *cpu_list; 40 const char *cpu_list;
@@ -46,6 +47,7 @@ struct perf_top {
46 int realtime_prio; 47 int realtime_prio;
47 int sym_pcnt_filter; 48 int sym_pcnt_filter;
48 const char *sym_filter; 49 const char *sym_filter;
50 const char *uid_str;
49}; 51};
50 52
51size_t perf_top__header_snprintf(struct perf_top *top, char *bf, size_t size); 53size_t perf_top__header_snprintf(struct perf_top *top, char *bf, size_t size);
diff --git a/tools/perf/util/trace-event-parse.c b/tools/perf/util/trace-event-parse.c
index 1a8d4dc4f386..a4088ced1e64 100644
--- a/tools/perf/util/trace-event-parse.c
+++ b/tools/perf/util/trace-event-parse.c
@@ -25,7 +25,6 @@
25#include <stdio.h> 25#include <stdio.h>
26#include <stdlib.h> 26#include <stdlib.h>
27#include <string.h> 27#include <string.h>
28#include <ctype.h>
29#include <errno.h> 28#include <errno.h>
30 29
31#include "../perf.h" 30#include "../perf.h"
@@ -1424,6 +1423,11 @@ static long long arg_num_eval(struct print_arg *arg)
1424 die("unknown op '%s'", arg->op.op); 1423 die("unknown op '%s'", arg->op.op);
1425 } 1424 }
1426 break; 1425 break;
1426 case '+':
1427 left = arg_num_eval(arg->op.left);
1428 right = arg_num_eval(arg->op.right);
1429 val = left + right;
1430 break;
1427 default: 1431 default:
1428 die("unknown op '%s'", arg->op.op); 1432 die("unknown op '%s'", arg->op.op);
1429 } 1433 }
@@ -1484,6 +1488,13 @@ process_fields(struct event *event, struct print_flag_sym **list, char **tok)
1484 1488
1485 free_token(token); 1489 free_token(token);
1486 type = process_arg(event, arg, &token); 1490 type = process_arg(event, arg, &token);
1491
1492 if (type == EVENT_OP)
1493 type = process_op(event, arg, &token);
1494
1495 if (type == EVENT_ERROR)
1496 goto out_free;
1497
1487 if (test_type_token(type, token, EVENT_DELIM, ",")) 1498 if (test_type_token(type, token, EVENT_DELIM, ","))
1488 goto out_free; 1499 goto out_free;
1489 1500
diff --git a/tools/perf/util/trace-event-read.c b/tools/perf/util/trace-event-read.c
index f55cc3a765a1..b9592e0de8d7 100644
--- a/tools/perf/util/trace-event-read.c
+++ b/tools/perf/util/trace-event-read.c
@@ -33,7 +33,6 @@
33#include <pthread.h> 33#include <pthread.h>
34#include <fcntl.h> 34#include <fcntl.h>
35#include <unistd.h> 35#include <unistd.h>
36#include <ctype.h>
37#include <errno.h> 36#include <errno.h>
38 37
39#include "../perf.h" 38#include "../perf.h"
diff --git a/tools/perf/util/trace-event-scripting.c b/tools/perf/util/trace-event-scripting.c
index a3fdf55f317b..18ae6c1831d3 100644
--- a/tools/perf/util/trace-event-scripting.c
+++ b/tools/perf/util/trace-event-scripting.c
@@ -22,7 +22,6 @@
22#include <stdio.h> 22#include <stdio.h>
23#include <stdlib.h> 23#include <stdlib.h>
24#include <string.h> 24#include <string.h>
25#include <ctype.h>
26#include <errno.h> 25#include <errno.h>
27 26
28#include "../perf.h" 27#include "../perf.h"
diff --git a/tools/perf/util/ui/browsers/hists.c b/tools/perf/util/ui/browsers/hists.c
index e81aef1f2569..bfba0490c098 100644
--- a/tools/perf/util/ui/browsers/hists.c
+++ b/tools/perf/util/ui/browsers/hists.c
@@ -839,6 +839,9 @@ static int hists__browser_title(struct hists *self, char *bf, size_t size,
839 nr_events = convert_unit(nr_events, &unit); 839 nr_events = convert_unit(nr_events, &unit);
840 printed = snprintf(bf, size, "Events: %lu%c %s", nr_events, unit, ev_name); 840 printed = snprintf(bf, size, "Events: %lu%c %s", nr_events, unit, ev_name);
841 841
842 if (self->uid_filter_str)
843 printed += snprintf(bf + printed, size - printed,
844 ", UID: %s", self->uid_filter_str);
842 if (thread) 845 if (thread)
843 printed += snprintf(bf + printed, size - printed, 846 printed += snprintf(bf + printed, size - printed,
844 ", Thread: %s(%d)", 847 ", Thread: %s(%d)",
diff --git a/tools/perf/util/ui/browsers/map.c b/tools/perf/util/ui/browsers/map.c
index 6905bcc8be2d..eca6575abfd0 100644
--- a/tools/perf/util/ui/browsers/map.c
+++ b/tools/perf/util/ui/browsers/map.c
@@ -3,9 +3,9 @@
3#include <newt.h> 3#include <newt.h>
4#include <inttypes.h> 4#include <inttypes.h>
5#include <sys/ttydefaults.h> 5#include <sys/ttydefaults.h>
6#include <ctype.h>
7#include <string.h> 6#include <string.h>
8#include <linux/bitops.h> 7#include <linux/bitops.h>
8#include "../../util.h"
9#include "../../debug.h" 9#include "../../debug.h"
10#include "../../symbol.h" 10#include "../../symbol.h"
11#include "../browser.h" 11#include "../browser.h"
diff --git a/tools/perf/util/usage.c b/tools/perf/util/usage.c
index d76d1c0ff98f..52bb07c6442a 100644
--- a/tools/perf/util/usage.c
+++ b/tools/perf/util/usage.c
@@ -7,6 +7,7 @@
7 * Copyright (C) Linus Torvalds, 2005 7 * Copyright (C) Linus Torvalds, 2005
8 */ 8 */
9#include "util.h" 9#include "util.h"
10#include "debug.h"
10 11
11static void report(const char *prefix, const char *err, va_list params) 12static void report(const char *prefix, const char *err, va_list params)
12{ 13{
@@ -81,3 +82,41 @@ void warning(const char *warn, ...)
81 warn_routine(warn, params); 82 warn_routine(warn, params);
82 va_end(params); 83 va_end(params);
83} 84}
85
86uid_t parse_target_uid(const char *str, const char *tid, const char *pid)
87{
88 struct passwd pwd, *result;
89 char buf[1024];
90
91 if (str == NULL)
92 return UINT_MAX;
93
94 /* UID and PID are mutually exclusive */
95 if (tid || pid) {
96 ui__warning("PID/TID switch overriding UID\n");
97 sleep(1);
98 return UINT_MAX;
99 }
100
101 getpwnam_r(str, &pwd, buf, sizeof(buf), &result);
102
103 if (result == NULL) {
104 char *endptr;
105 int uid = strtol(str, &endptr, 10);
106
107 if (*endptr != '\0') {
108 ui__error("Invalid user %s\n", str);
109 return UINT_MAX - 1;
110 }
111
112 getpwuid_r(uid, &pwd, buf, sizeof(buf), &result);
113
114 if (result == NULL) {
115 ui__error("Problems obtaining information for user %s\n",
116 str);
117 return UINT_MAX - 1;
118 }
119 }
120
121 return result->pw_uid;
122}
diff --git a/tools/perf/util/util.c b/tools/perf/util/util.c
index fb25d1329218..8109a907841e 100644
--- a/tools/perf/util/util.c
+++ b/tools/perf/util/util.c
@@ -14,6 +14,8 @@ void event_attr_init(struct perf_event_attr *attr)
14 attr->exclude_host = 1; 14 attr->exclude_host = 1;
15 if (!perf_guest) 15 if (!perf_guest)
16 attr->exclude_guest = 1; 16 attr->exclude_guest = 1;
17 /* to capture ABI version */
18 attr->size = sizeof(*attr);
17} 19}
18 20
19int mkdir_p(char *path, mode_t mode) 21int mkdir_p(char *path, mode_t mode)
diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h
index ecf9898169c8..0f99f394d8e0 100644
--- a/tools/perf/util/util.h
+++ b/tools/perf/util/util.h
@@ -199,6 +199,8 @@ static inline int has_extension(const char *filename, const char *ext)
199#undef isalpha 199#undef isalpha
200#undef isprint 200#undef isprint
201#undef isalnum 201#undef isalnum
202#undef islower
203#undef isupper
202#undef tolower 204#undef tolower
203#undef toupper 205#undef toupper
204 206
@@ -219,6 +221,8 @@ extern unsigned char sane_ctype[256];
219#define isalpha(x) sane_istest(x,GIT_ALPHA) 221#define isalpha(x) sane_istest(x,GIT_ALPHA)
220#define isalnum(x) sane_istest(x,GIT_ALPHA | GIT_DIGIT) 222#define isalnum(x) sane_istest(x,GIT_ALPHA | GIT_DIGIT)
221#define isprint(x) sane_istest(x,GIT_PRINT) 223#define isprint(x) sane_istest(x,GIT_PRINT)
224#define islower(x) (sane_istest(x,GIT_ALPHA) && sane_istest(x,0x20))
225#define isupper(x) (sane_istest(x,GIT_ALPHA) && !sane_istest(x,0x20))
222#define tolower(x) sane_case((unsigned char)(x), 0x20) 226#define tolower(x) sane_case((unsigned char)(x), 0x20)
223#define toupper(x) sane_case((unsigned char)(x), 0) 227#define toupper(x) sane_case((unsigned char)(x), 0)
224 228
@@ -245,6 +249,8 @@ struct perf_event_attr;
245 249
246void event_attr_init(struct perf_event_attr *attr); 250void event_attr_init(struct perf_event_attr *attr);
247 251
252uid_t parse_target_uid(const char *str, const char *tid, const char *pid);
253
248#define _STR(x) #x 254#define _STR(x) #x
249#define STR(x) _STR(x) 255#define STR(x) _STR(x)
250 256