aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIngo Molnar <mingo@kernel.org>2013-12-05 04:55:07 -0500
committerIngo Molnar <mingo@kernel.org>2013-12-05 04:55:07 -0500
commit00f1762dcc43097b8f9c88d3a0aca7762da642d3 (patch)
tree37b2b61811c16f687a0af54ca54991503a07327f
parent89e3bbd58a6186b832fe2b9419ac2f9ab90e9089 (diff)
parent6d65894bc028d0342829ea1e64c9e9efad571124 (diff)
Merge tag 'perf-core-for-mingo' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/core
Pull perf/core improvements and fixes from Arnaldo Carvalho de Melo: * Backport libtraceevent plugin support from trace-cmd repository, with plugins for jbd2, hrtimer, kmem, kvm, mac80211, sched_switch, function, xen, scsi, cfg80211. From Jiri Olsa. * Retain bfd reference to lookup source line numbers, greatly optimizing, among other use cases, 'perf report -s srcline', from Adrian Hunter. * Do not disable source line lookup just because of one failure, from Adrian Hunter. * Fix random fd closing with no libelf, from Adrian Hunter. * Do not call perf_event__preprocess_sample() twice in 'perf script', from Adrian Hunter. * Several 'perf kvm' man page corrections, from Dongsheng Yang. Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> Signed-off-by: Ingo Molnar <mingo@kernel.org>
-rw-r--r--tools/lib/traceevent/Makefile71
-rw-r--r--tools/lib/traceevent/event-parse.c56
-rw-r--r--tools/lib/traceevent/event-parse.h19
-rw-r--r--tools/lib/traceevent/event-plugin.c215
-rw-r--r--tools/lib/traceevent/plugin_cfg80211.c24
-rw-r--r--tools/lib/traceevent/plugin_function.c160
-rw-r--r--tools/lib/traceevent/plugin_hrtimer.c78
-rw-r--r--tools/lib/traceevent/plugin_jbd2.c68
-rw-r--r--tools/lib/traceevent/plugin_kmem.c72
-rw-r--r--tools/lib/traceevent/plugin_kvm.c436
-rw-r--r--tools/lib/traceevent/plugin_mac80211.c95
-rw-r--r--tools/lib/traceevent/plugin_sched_switch.c148
-rw-r--r--tools/lib/traceevent/plugin_scsi.c423
-rw-r--r--tools/lib/traceevent/plugin_xen.c130
-rw-r--r--tools/perf/Documentation/perf-kvm.txt27
-rw-r--r--tools/perf/Makefile.perf18
-rw-r--r--tools/perf/builtin-script.c13
-rw-r--r--tools/perf/builtin-trace.c5
-rw-r--r--tools/perf/config/Makefile13
-rw-r--r--tools/perf/config/feature-checks/Makefile6
-rw-r--r--tools/perf/config/feature-checks/test-stackprotector.c6
-rw-r--r--tools/perf/util/debug.c30
-rw-r--r--tools/perf/util/debug.h2
-rw-r--r--tools/perf/util/dso.c3
-rw-r--r--tools/perf/util/dso.h5
-rw-r--r--tools/perf/util/evlist.c8
-rw-r--r--tools/perf/util/evsel.c44
-rw-r--r--tools/perf/util/header.c8
-rw-r--r--tools/perf/util/machine.c14
-rw-r--r--tools/perf/util/python-ext-sources1
-rw-r--r--tools/perf/util/session.c31
-rw-r--r--tools/perf/util/session.h7
-rw-r--r--tools/perf/util/srcline.c66
-rw-r--r--tools/perf/util/symbol-minimal.c1
-rw-r--r--tools/perf/util/symbol.c2
-rw-r--r--tools/perf/util/target.h13
-rw-r--r--tools/perf/util/trace-event-parse.c13
-rw-r--r--tools/perf/util/trace-event-read.c20
-rw-r--r--tools/perf/util/trace-event.c82
-rw-r--r--tools/perf/util/trace-event.h15
-rw-r--r--tools/perf/util/util.c49
-rw-r--r--tools/perf/util/util.h1
42 files changed, 2305 insertions, 193 deletions
diff --git a/tools/lib/traceevent/Makefile b/tools/lib/traceevent/Makefile
index fc1502098595..0d9cbb426b44 100644
--- a/tools/lib/traceevent/Makefile
+++ b/tools/lib/traceevent/Makefile
@@ -43,6 +43,30 @@ man_dir_SQ = '$(subst ','\'',$(man_dir))'
43export man_dir man_dir_SQ INSTALL 43export man_dir man_dir_SQ INSTALL
44export DESTDIR DESTDIR_SQ 44export DESTDIR DESTDIR_SQ
45 45
46set_plugin_dir := 1
47
48# Set plugin_dir to preffered global plugin location
49# If we install under $HOME directory we go under
50# $(HOME)/.traceevent/plugins
51#
52# We dont set PLUGIN_DIR in case we install under $HOME
53# directory, because by default the code looks under:
54# $(HOME)/.traceevent/plugins by default.
55#
56ifeq ($(plugin_dir),)
57ifeq ($(prefix),$(HOME))
58override plugin_dir = $(HOME)/.traceevent/plugins
59set_plugin_dir := 0
60else
61override plugin_dir = $(prefix)/lib/traceevent/plugins
62endif
63endif
64
65ifeq ($(set_plugin_dir),1)
66PLUGIN_DIR = -DPLUGIN_DIR="$(DESTDIR)/$(plugin_dir)"
67PLUGIN_DIR_SQ = '$(subst ','\'',$(PLUGIN_DIR))'
68endif
69
46# copy a bit from Linux kbuild 70# copy a bit from Linux kbuild
47 71
48ifeq ("$(origin V)", "command line") 72ifeq ("$(origin V)", "command line")
@@ -96,6 +120,7 @@ export prefix bindir src obj
96# Shell quotes 120# Shell quotes
97bindir_SQ = $(subst ','\'',$(bindir)) 121bindir_SQ = $(subst ','\'',$(bindir))
98bindir_relative_SQ = $(subst ','\'',$(bindir_relative)) 122bindir_relative_SQ = $(subst ','\'',$(bindir_relative))
123plugin_dir_SQ = $(subst ','\'',$(plugin_dir))
99 124
100LIB_FILE = libtraceevent.a libtraceevent.so 125LIB_FILE = libtraceevent.a libtraceevent.so
101 126
@@ -138,10 +163,10 @@ else
138 print_app_build = echo ' BUILD '$(OBJ); 163 print_app_build = echo ' BUILD '$(OBJ);
139 print_fpic_compile = echo ' CC FPIC '$(OBJ); 164 print_fpic_compile = echo ' CC FPIC '$(OBJ);
140 print_shared_lib_compile = echo ' BUILD SHARED LIB '$(OBJ); 165 print_shared_lib_compile = echo ' BUILD SHARED LIB '$(OBJ);
141 print_plugin_obj_compile = echo ' BUILD PLUGIN OBJ '$(OBJ); 166 print_plugin_obj_compile = echo ' CC FPIC '$(OBJ);
142 print_plugin_build = echo ' BUILD PLUGIN '$(OBJ); 167 print_plugin_build = echo ' BUILD PLUGIN '$(OBJ);
143 print_static_lib_build = echo ' BUILD STATIC LIB '$(OBJ); 168 print_static_lib_build = echo ' BUILD STATIC LIB '$(OBJ);
144 print_install = echo ' INSTALL '$1' to $(DESTDIR_SQ)$2'; 169 print_install = echo ' INSTALL '$1;
145endif 170endif
146 171
147do_fpic_compile = \ 172do_fpic_compile = \
@@ -180,12 +205,29 @@ $(obj)/%.o: $(src)/%.c
180%.o: $(src)/%.c 205%.o: $(src)/%.c
181 $(Q)$(call do_compile) 206 $(Q)$(call do_compile)
182 207
183PEVENT_LIB_OBJS = event-parse.o trace-seq.o parse-filter.o parse-utils.o 208PEVENT_LIB_OBJS = event-parse.o
209PEVENT_LIB_OBJS += event-plugin.o
210PEVENT_LIB_OBJS += trace-seq.o
211PEVENT_LIB_OBJS += parse-filter.o
212PEVENT_LIB_OBJS += parse-utils.o
184PEVENT_LIB_OBJS += kbuffer-parse.o 213PEVENT_LIB_OBJS += kbuffer-parse.o
185 214
186ALL_OBJS = $(PEVENT_LIB_OBJS) 215PLUGIN_OBJS = plugin_jbd2.o
216PLUGIN_OBJS += plugin_hrtimer.o
217PLUGIN_OBJS += plugin_kmem.o
218PLUGIN_OBJS += plugin_kvm.o
219PLUGIN_OBJS += plugin_mac80211.o
220PLUGIN_OBJS += plugin_sched_switch.o
221PLUGIN_OBJS += plugin_function.o
222PLUGIN_OBJS += plugin_xen.o
223PLUGIN_OBJS += plugin_scsi.o
224PLUGIN_OBJS += plugin_cfg80211.o
225
226PLUGINS := $(PLUGIN_OBJS:.o=.so)
187 227
188CMD_TARGETS = $(LIB_FILE) 228ALL_OBJS = $(PEVENT_LIB_OBJS) $(PLUGIN_OBJS)
229
230CMD_TARGETS = $(LIB_FILE) $(PLUGINS)
189 231
190TARGETS = $(CMD_TARGETS) 232TARGETS = $(CMD_TARGETS)
191 233
@@ -200,9 +242,17 @@ libtraceevent.so: $(PEVENT_LIB_OBJS)
200libtraceevent.a: $(PEVENT_LIB_OBJS) 242libtraceevent.a: $(PEVENT_LIB_OBJS)
201 $(Q)$(do_build_static_lib) 243 $(Q)$(do_build_static_lib)
202 244
245plugins: $(PLUGINS)
246
203$(PEVENT_LIB_OBJS): %.o: $(src)/%.c TRACEEVENT-CFLAGS 247$(PEVENT_LIB_OBJS): %.o: $(src)/%.c TRACEEVENT-CFLAGS
204 $(Q)$(do_fpic_compile) 248 $(Q)$(do_fpic_compile)
205 249
250$(PLUGIN_OBJS): %.o : $(src)/%.c
251 $(Q)$(do_compile_plugin_obj)
252
253$(PLUGINS): %.so: %.o
254 $(Q)$(do_plugin_build)
255
206define make_version.h 256define make_version.h
207 (echo '/* This file is automatically generated. Do not modify. */'; \ 257 (echo '/* This file is automatically generated. Do not modify. */'; \
208 echo \#define VERSION_CODE $(shell \ 258 echo \#define VERSION_CODE $(shell \
@@ -290,9 +340,16 @@ define do_install
290 $(INSTALL) $1 '$(DESTDIR_SQ)$2' 340 $(INSTALL) $1 '$(DESTDIR_SQ)$2'
291endef 341endef
292 342
293install_lib: all_cmd 343install_lib: all_cmd install_plugins
294 $(Q)$(call do_install,$(LIB_FILE),$(bindir_SQ)) 344 $(Q)$(call do_install,$(LIB_FILE),$(bindir_SQ))
295 345
346PLUGINS_INSTALL = $(subst .so,.install,$(PLUGINS))
347
348$(PLUGINS_INSTALL): %.install : %.so force
349 $(Q)$(call do_install,$<,$(plugin_dir_SQ))
350
351install_plugins: $(PLUGINS_INSTALL)
352
296install: install_lib 353install: install_lib
297 354
298clean: 355clean:
diff --git a/tools/lib/traceevent/event-parse.c b/tools/lib/traceevent/event-parse.c
index 900fca01bdd3..9849873265d4 100644
--- a/tools/lib/traceevent/event-parse.c
+++ b/tools/lib/traceevent/event-parse.c
@@ -5121,8 +5121,38 @@ enum pevent_errno __pevent_parse_format(struct event_format **eventp,
5121 return ret; 5121 return ret;
5122} 5122}
5123 5123
5124static enum pevent_errno
5125__pevent_parse_event(struct pevent *pevent,
5126 struct event_format **eventp,
5127 const char *buf, unsigned long size,
5128 const char *sys)
5129{
5130 int ret = __pevent_parse_format(eventp, pevent, buf, size, sys);
5131 struct event_format *event = *eventp;
5132
5133 if (event == NULL)
5134 return ret;
5135
5136 if (pevent && add_event(pevent, event)) {
5137 ret = PEVENT_ERRNO__MEM_ALLOC_FAILED;
5138 goto event_add_failed;
5139 }
5140
5141#define PRINT_ARGS 0
5142 if (PRINT_ARGS && event->print_fmt.args)
5143 print_args(event->print_fmt.args);
5144
5145 return 0;
5146
5147event_add_failed:
5148 pevent_free_format(event);
5149 return ret;
5150}
5151
5124/** 5152/**
5125 * pevent_parse_format - parse the event format 5153 * pevent_parse_format - parse the event format
5154 * @pevent: the handle to the pevent
5155 * @eventp: returned format
5126 * @buf: the buffer storing the event format string 5156 * @buf: the buffer storing the event format string
5127 * @size: the size of @buf 5157 * @size: the size of @buf
5128 * @sys: the system the event belongs to 5158 * @sys: the system the event belongs to
@@ -5134,10 +5164,12 @@ enum pevent_errno __pevent_parse_format(struct event_format **eventp,
5134 * 5164 *
5135 * /sys/kernel/debug/tracing/events/.../.../format 5165 * /sys/kernel/debug/tracing/events/.../.../format
5136 */ 5166 */
5137enum pevent_errno pevent_parse_format(struct event_format **eventp, const char *buf, 5167enum pevent_errno pevent_parse_format(struct pevent *pevent,
5168 struct event_format **eventp,
5169 const char *buf,
5138 unsigned long size, const char *sys) 5170 unsigned long size, const char *sys)
5139{ 5171{
5140 return __pevent_parse_format(eventp, NULL, buf, size, sys); 5172 return __pevent_parse_event(pevent, eventp, buf, size, sys);
5141} 5173}
5142 5174
5143/** 5175/**
@@ -5158,25 +5190,7 @@ enum pevent_errno pevent_parse_event(struct pevent *pevent, const char *buf,
5158 unsigned long size, const char *sys) 5190 unsigned long size, const char *sys)
5159{ 5191{
5160 struct event_format *event = NULL; 5192 struct event_format *event = NULL;
5161 int ret = __pevent_parse_format(&event, pevent, buf, size, sys); 5193 return __pevent_parse_event(pevent, &event, buf, size, sys);
5162
5163 if (event == NULL)
5164 return ret;
5165
5166 if (add_event(pevent, event)) {
5167 ret = PEVENT_ERRNO__MEM_ALLOC_FAILED;
5168 goto event_add_failed;
5169 }
5170
5171#define PRINT_ARGS 0
5172 if (PRINT_ARGS && event->print_fmt.args)
5173 print_args(event->print_fmt.args);
5174
5175 return 0;
5176
5177event_add_failed:
5178 pevent_free_format(event);
5179 return ret;
5180} 5194}
5181 5195
5182#undef _PE 5196#undef _PE
diff --git a/tools/lib/traceevent/event-parse.h b/tools/lib/traceevent/event-parse.h
index 8d73d2594f65..620c27a72960 100644
--- a/tools/lib/traceevent/event-parse.h
+++ b/tools/lib/traceevent/event-parse.h
@@ -23,6 +23,7 @@
23#include <stdbool.h> 23#include <stdbool.h>
24#include <stdarg.h> 24#include <stdarg.h>
25#include <regex.h> 25#include <regex.h>
26#include <string.h>
26 27
27#ifndef __maybe_unused 28#ifndef __maybe_unused
28#define __maybe_unused __attribute__((unused)) 29#define __maybe_unused __attribute__((unused))
@@ -377,6 +378,11 @@ enum pevent_errno {
377}; 378};
378#undef _PE 379#undef _PE
379 380
381struct plugin_list;
382
383struct plugin_list *traceevent_load_plugins(struct pevent *pevent);
384void traceevent_unload_plugins(struct plugin_list *plugin_list);
385
380struct cmdline; 386struct cmdline;
381struct cmdline_list; 387struct cmdline_list;
382struct func_map; 388struct func_map;
@@ -522,6 +528,15 @@ __data2host8(struct pevent *pevent, unsigned long long data)
522 __data2host8(pevent, __val); \ 528 __data2host8(pevent, __val); \
523}) 529})
524 530
531static inline int traceevent_host_bigendian(void)
532{
533 unsigned char str[] = { 0x1, 0x2, 0x3, 0x4 };
534 unsigned int val;
535
536 memcpy(&val, str, 4);
537 return val == 0x01020304;
538}
539
525/* taken from kernel/trace/trace.h */ 540/* taken from kernel/trace/trace.h */
526enum trace_flag_type { 541enum trace_flag_type {
527 TRACE_FLAG_IRQS_OFF = 0x01, 542 TRACE_FLAG_IRQS_OFF = 0x01,
@@ -547,7 +562,9 @@ int pevent_parse_header_page(struct pevent *pevent, char *buf, unsigned long siz
547 562
548enum pevent_errno pevent_parse_event(struct pevent *pevent, const char *buf, 563enum pevent_errno pevent_parse_event(struct pevent *pevent, const char *buf,
549 unsigned long size, const char *sys); 564 unsigned long size, const char *sys);
550enum pevent_errno pevent_parse_format(struct event_format **eventp, const char *buf, 565enum pevent_errno pevent_parse_format(struct pevent *pevent,
566 struct event_format **eventp,
567 const char *buf,
551 unsigned long size, const char *sys); 568 unsigned long size, const char *sys);
552void pevent_free_format(struct event_format *event); 569void pevent_free_format(struct event_format *event);
553 570
diff --git a/tools/lib/traceevent/event-plugin.c b/tools/lib/traceevent/event-plugin.c
new file mode 100644
index 000000000000..125f5676bcb5
--- /dev/null
+++ b/tools/lib/traceevent/event-plugin.c
@@ -0,0 +1,215 @@
1/*
2 * Copyright (C) 2009, 2010 Red Hat Inc, Steven Rostedt <srostedt@redhat.com>
3 *
4 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation;
8 * version 2.1 of the License (not later!)
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this program; if not, see <http://www.gnu.org/licenses>
17 *
18 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
19 */
20
21#include <string.h>
22#include <dlfcn.h>
23#include <stdlib.h>
24#include <sys/types.h>
25#include <sys/stat.h>
26#include <unistd.h>
27#include <dirent.h>
28#include "event-parse.h"
29#include "event-utils.h"
30
31#define LOCAL_PLUGIN_DIR ".traceevent/plugins"
32
33struct plugin_list {
34 struct plugin_list *next;
35 char *name;
36 void *handle;
37};
38
39static void
40load_plugin(struct pevent *pevent, const char *path,
41 const char *file, void *data)
42{
43 struct plugin_list **plugin_list = data;
44 pevent_plugin_load_func func;
45 struct plugin_list *list;
46 const char *alias;
47 char *plugin;
48 void *handle;
49
50 plugin = malloc(strlen(path) + strlen(file) + 2);
51 if (!plugin) {
52 warning("could not allocate plugin memory\n");
53 return;
54 }
55
56 strcpy(plugin, path);
57 strcat(plugin, "/");
58 strcat(plugin, file);
59
60 handle = dlopen(plugin, RTLD_NOW | RTLD_GLOBAL);
61 if (!handle) {
62 warning("could not load plugin '%s'\n%s\n",
63 plugin, dlerror());
64 goto out_free;
65 }
66
67 alias = dlsym(handle, PEVENT_PLUGIN_ALIAS_NAME);
68 if (!alias)
69 alias = file;
70
71 func = dlsym(handle, PEVENT_PLUGIN_LOADER_NAME);
72 if (!func) {
73 warning("could not find func '%s' in plugin '%s'\n%s\n",
74 PEVENT_PLUGIN_LOADER_NAME, plugin, dlerror());
75 goto out_free;
76 }
77
78 list = malloc(sizeof(*list));
79 if (!list) {
80 warning("could not allocate plugin memory\n");
81 goto out_free;
82 }
83
84 list->next = *plugin_list;
85 list->handle = handle;
86 list->name = plugin;
87 *plugin_list = list;
88
89 pr_stat("registering plugin: %s", plugin);
90 func(pevent);
91 return;
92
93 out_free:
94 free(plugin);
95}
96
97static void
98load_plugins_dir(struct pevent *pevent, const char *suffix,
99 const char *path,
100 void (*load_plugin)(struct pevent *pevent,
101 const char *path,
102 const char *name,
103 void *data),
104 void *data)
105{
106 struct dirent *dent;
107 struct stat st;
108 DIR *dir;
109 int ret;
110
111 ret = stat(path, &st);
112 if (ret < 0)
113 return;
114
115 if (!S_ISDIR(st.st_mode))
116 return;
117
118 dir = opendir(path);
119 if (!dir)
120 return;
121
122 while ((dent = readdir(dir))) {
123 const char *name = dent->d_name;
124
125 if (strcmp(name, ".") == 0 ||
126 strcmp(name, "..") == 0)
127 continue;
128
129 /* Only load plugins that end in suffix */
130 if (strcmp(name + (strlen(name) - strlen(suffix)), suffix) != 0)
131 continue;
132
133 load_plugin(pevent, path, name, data);
134 }
135
136 closedir(dir);
137}
138
139static void
140load_plugins(struct pevent *pevent, const char *suffix,
141 void (*load_plugin)(struct pevent *pevent,
142 const char *path,
143 const char *name,
144 void *data),
145 void *data)
146{
147 char *home;
148 char *path;
149 char *envdir;
150
151 /*
152 * If a system plugin directory was defined,
153 * check that first.
154 */
155#ifdef PLUGIN_DIR
156 load_plugins_dir(pevent, suffix, PLUGIN_DIR, load_plugin, data);
157#endif
158
159 /*
160 * Next let the environment-set plugin directory
161 * override the system defaults.
162 */
163 envdir = getenv("TRACEEVENT_PLUGIN_DIR");
164 if (envdir)
165 load_plugins_dir(pevent, suffix, envdir, load_plugin, data);
166
167 /*
168 * Now let the home directory override the environment
169 * or system defaults.
170 */
171 home = getenv("HOME");
172 if (!home)
173 return;
174
175 path = malloc(strlen(home) + strlen(LOCAL_PLUGIN_DIR) + 2);
176 if (!path) {
177 warning("could not allocate plugin memory\n");
178 return;
179 }
180
181 strcpy(path, home);
182 strcat(path, "/");
183 strcat(path, LOCAL_PLUGIN_DIR);
184
185 load_plugins_dir(pevent, suffix, path, load_plugin, data);
186
187 free(path);
188}
189
190struct plugin_list*
191traceevent_load_plugins(struct pevent *pevent)
192{
193 struct plugin_list *list = NULL;
194
195 load_plugins(pevent, ".so", load_plugin, &list);
196 return list;
197}
198
199void
200traceevent_unload_plugins(struct plugin_list *plugin_list)
201{
202 pevent_plugin_unload_func func;
203 struct plugin_list *list;
204
205 while (plugin_list) {
206 list = plugin_list;
207 plugin_list = list->next;
208 func = dlsym(list->handle, PEVENT_PLUGIN_UNLOADER_NAME);
209 if (func)
210 func();
211 dlclose(list->handle);
212 free(list->name);
213 free(list);
214 }
215}
diff --git a/tools/lib/traceevent/plugin_cfg80211.c b/tools/lib/traceevent/plugin_cfg80211.c
new file mode 100644
index 000000000000..dcab8e873c21
--- /dev/null
+++ b/tools/lib/traceevent/plugin_cfg80211.c
@@ -0,0 +1,24 @@
1#include <stdio.h>
2#include <string.h>
3#include <inttypes.h>
4#include <endian.h>
5#include "event-parse.h"
6
7static unsigned long long
8process___le16_to_cpup(struct trace_seq *s,
9 unsigned long long *args)
10{
11 uint16_t *val = (uint16_t *) args[0];
12 return val ? (long long) le16toh(*val) : 0;
13}
14
15int PEVENT_PLUGIN_LOADER(struct pevent *pevent)
16{
17 pevent_register_print_function(pevent,
18 process___le16_to_cpup,
19 PEVENT_FUNC_ARG_INT,
20 "__le16_to_cpup",
21 PEVENT_FUNC_ARG_PTR,
22 PEVENT_FUNC_ARG_VOID);
23 return 0;
24}
diff --git a/tools/lib/traceevent/plugin_function.c b/tools/lib/traceevent/plugin_function.c
new file mode 100644
index 000000000000..aad92ad5e96f
--- /dev/null
+++ b/tools/lib/traceevent/plugin_function.c
@@ -0,0 +1,160 @@
1/*
2 * Copyright (C) 2009, 2010 Red Hat Inc, Steven Rostedt <srostedt@redhat.com>
3 *
4 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation;
8 * version 2.1 of the License (not later!)
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this program; if not, see <http://www.gnu.org/licenses>
17 *
18 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
19 */
20#include <stdio.h>
21#include <stdlib.h>
22#include <string.h>
23
24#include "event-parse.h"
25#include "event-utils.h"
26
27static struct func_stack {
28 int size;
29 char **stack;
30} *fstack;
31
32static int cpus = -1;
33
34#define STK_BLK 10
35
36static void add_child(struct func_stack *stack, const char *child, int pos)
37{
38 int i;
39
40 if (!child)
41 return;
42
43 if (pos < stack->size)
44 free(stack->stack[pos]);
45 else {
46 char **ptr;
47
48 ptr = realloc(stack->stack, sizeof(char *) *
49 (stack->size + STK_BLK));
50 if (!ptr) {
51 warning("could not allocate plugin memory\n");
52 return;
53 }
54
55 stack->stack = ptr;
56
57 for (i = stack->size; i < stack->size + STK_BLK; i++)
58 stack->stack[i] = NULL;
59 stack->size += STK_BLK;
60 }
61
62 stack->stack[pos] = strdup(child);
63}
64
65static int add_and_get_index(const char *parent, const char *child, int cpu)
66{
67 int i;
68
69 if (cpu < 0)
70 return 0;
71
72 if (cpu > cpus) {
73 struct func_stack *ptr;
74
75 ptr = realloc(fstack, sizeof(*fstack) * (cpu + 1));
76 if (!ptr) {
77 warning("could not allocate plugin memory\n");
78 return 0;
79 }
80
81 fstack = ptr;
82
83 /* Account for holes in the cpu count */
84 for (i = cpus + 1; i <= cpu; i++)
85 memset(&fstack[i], 0, sizeof(fstack[i]));
86 cpus = cpu;
87 }
88
89 for (i = 0; i < fstack[cpu].size && fstack[cpu].stack[i]; i++) {
90 if (strcmp(parent, fstack[cpu].stack[i]) == 0) {
91 add_child(&fstack[cpu], child, i+1);
92 return i;
93 }
94 }
95
96 /* Not found */
97 add_child(&fstack[cpu], parent, 0);
98 add_child(&fstack[cpu], child, 1);
99 return 0;
100}
101
102static int function_handler(struct trace_seq *s, struct pevent_record *record,
103 struct event_format *event, void *context)
104{
105 struct pevent *pevent = event->pevent;
106 unsigned long long function;
107 unsigned long long pfunction;
108 const char *func;
109 const char *parent;
110 int index;
111
112 if (pevent_get_field_val(s, event, "ip", record, &function, 1))
113 return trace_seq_putc(s, '!');
114
115 func = pevent_find_function(pevent, function);
116
117 if (pevent_get_field_val(s, event, "parent_ip", record, &pfunction, 1))
118 return trace_seq_putc(s, '!');
119
120 parent = pevent_find_function(pevent, pfunction);
121
122 index = add_and_get_index(parent, func, record->cpu);
123
124 trace_seq_printf(s, "%*s", index*3, "");
125
126 if (func)
127 trace_seq_printf(s, "%s", func);
128 else
129 trace_seq_printf(s, "0x%llx", function);
130
131 trace_seq_printf(s, " <-- ");
132 if (parent)
133 trace_seq_printf(s, "%s", parent);
134 else
135 trace_seq_printf(s, "0x%llx", pfunction);
136
137 return 0;
138}
139
140int PEVENT_PLUGIN_LOADER(struct pevent *pevent)
141{
142 pevent_register_event_handler(pevent, -1, "ftrace", "function",
143 function_handler, NULL);
144 return 0;
145}
146
147void PEVENT_PLUGIN_UNLOADER(void)
148{
149 int i, x;
150
151 for (i = 0; i <= cpus; i++) {
152 for (x = 0; x < fstack[i].size && fstack[i].stack[x]; x++)
153 free(fstack[i].stack[x]);
154 free(fstack[i].stack);
155 }
156
157 free(fstack);
158 fstack = NULL;
159 cpus = -1;
160}
diff --git a/tools/lib/traceevent/plugin_hrtimer.c b/tools/lib/traceevent/plugin_hrtimer.c
new file mode 100644
index 000000000000..0b0ebf30aa44
--- /dev/null
+++ b/tools/lib/traceevent/plugin_hrtimer.c
@@ -0,0 +1,78 @@
1/*
2 * Copyright (C) 2009 Red Hat Inc, Steven Rostedt <srostedt@redhat.com>
3 * Copyright (C) 2009 Johannes Berg <johannes@sipsolutions.net>
4 *
5 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation;
9 * version 2.1 of the License (not later!)
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this program; if not, see <http://www.gnu.org/licenses>
18 *
19 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
20 */
21#include <stdio.h>
22#include <stdlib.h>
23#include <string.h>
24
25#include "event-parse.h"
26
27static int timer_expire_handler(struct trace_seq *s,
28 struct pevent_record *record,
29 struct event_format *event, void *context)
30{
31 trace_seq_printf(s, "hrtimer=");
32
33 if (pevent_print_num_field(s, "0x%llx", event, "timer",
34 record, 0) == -1)
35 pevent_print_num_field(s, "0x%llx", event, "hrtimer",
36 record, 1);
37
38 trace_seq_printf(s, " now=");
39
40 pevent_print_num_field(s, "%llu", event, "now", record, 1);
41
42 pevent_print_func_field(s, " function=%s", event, "function",
43 record, 0);
44 return 0;
45}
46
47static int timer_start_handler(struct trace_seq *s,
48 struct pevent_record *record,
49 struct event_format *event, void *context)
50{
51 trace_seq_printf(s, "hrtimer=");
52
53 if (pevent_print_num_field(s, "0x%llx", event, "timer",
54 record, 0) == -1)
55 pevent_print_num_field(s, "0x%llx", event, "hrtimer",
56 record, 1);
57
58 pevent_print_func_field(s, " function=%s", event, "function",
59 record, 0);
60
61 trace_seq_printf(s, " expires=");
62 pevent_print_num_field(s, "%llu", event, "expires", record, 1);
63
64 trace_seq_printf(s, " softexpires=");
65 pevent_print_num_field(s, "%llu", event, "softexpires", record, 1);
66 return 0;
67}
68
69int PEVENT_PLUGIN_LOADER(struct pevent *pevent)
70{
71 pevent_register_event_handler(pevent, -1,
72 "timer", "hrtimer_expire_entry",
73 timer_expire_handler, NULL);
74
75 pevent_register_event_handler(pevent, -1, "timer", "hrtimer_start",
76 timer_start_handler, NULL);
77 return 0;
78}
diff --git a/tools/lib/traceevent/plugin_jbd2.c b/tools/lib/traceevent/plugin_jbd2.c
new file mode 100644
index 000000000000..2f93f81f0bac
--- /dev/null
+++ b/tools/lib/traceevent/plugin_jbd2.c
@@ -0,0 +1,68 @@
1/*
2 * Copyright (C) 2010 Red Hat Inc, Steven Rostedt <srostedt@redhat.com>
3 *
4 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation;
8 * version 2.1 of the License (not later!)
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this program; if not, see <http://www.gnu.org/licenses>
17 *
18 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
19 */
20#include <stdio.h>
21#include <stdlib.h>
22#include <string.h>
23
24#include "event-parse.h"
25
26#define MINORBITS 20
27#define MINORMASK ((1U << MINORBITS) - 1)
28
29#define MAJOR(dev) ((unsigned int) ((dev) >> MINORBITS))
30#define MINOR(dev) ((unsigned int) ((dev) & MINORMASK))
31
32static unsigned long long
33process_jbd2_dev_to_name(struct trace_seq *s,
34 unsigned long long *args)
35{
36 unsigned int dev = args[0];
37
38 trace_seq_printf(s, "%d:%d", MAJOR(dev), MINOR(dev));
39 return 0;
40}
41
42static unsigned long long
43process_jiffies_to_msecs(struct trace_seq *s,
44 unsigned long long *args)
45{
46 unsigned long long jiffies = args[0];
47
48 trace_seq_printf(s, "%lld", jiffies);
49 return jiffies;
50}
51
52int PEVENT_PLUGIN_LOADER(struct pevent *pevent)
53{
54 pevent_register_print_function(pevent,
55 process_jbd2_dev_to_name,
56 PEVENT_FUNC_ARG_STRING,
57 "jbd2_dev_to_name",
58 PEVENT_FUNC_ARG_INT,
59 PEVENT_FUNC_ARG_VOID);
60
61 pevent_register_print_function(pevent,
62 process_jiffies_to_msecs,
63 PEVENT_FUNC_ARG_LONG,
64 "jiffies_to_msecs",
65 PEVENT_FUNC_ARG_LONG,
66 PEVENT_FUNC_ARG_VOID);
67 return 0;
68}
diff --git a/tools/lib/traceevent/plugin_kmem.c b/tools/lib/traceevent/plugin_kmem.c
new file mode 100644
index 000000000000..7115c8037ea8
--- /dev/null
+++ b/tools/lib/traceevent/plugin_kmem.c
@@ -0,0 +1,72 @@
1/*
2 * Copyright (C) 2009 Red Hat Inc, Steven Rostedt <srostedt@redhat.com>
3 *
4 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation;
8 * version 2.1 of the License (not later!)
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this program; if not, see <http://www.gnu.org/licenses>
17 *
18 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
19 */
20#include <stdio.h>
21#include <stdlib.h>
22#include <string.h>
23
24#include "event-parse.h"
25
26static int call_site_handler(struct trace_seq *s, struct pevent_record *record,
27 struct event_format *event, void *context)
28{
29 struct format_field *field;
30 unsigned long long val, addr;
31 void *data = record->data;
32 const char *func;
33
34 field = pevent_find_field(event, "call_site");
35 if (!field)
36 return 1;
37
38 if (pevent_read_number_field(field, data, &val))
39 return 1;
40
41 func = pevent_find_function(event->pevent, val);
42 if (!func)
43 return 1;
44
45 addr = pevent_find_function_address(event->pevent, val);
46
47 trace_seq_printf(s, "(%s+0x%x) ", func, (int)(val - addr));
48 return 1;
49}
50
51int PEVENT_PLUGIN_LOADER(struct pevent *pevent)
52{
53 pevent_register_event_handler(pevent, -1, "kmem", "kfree",
54 call_site_handler, NULL);
55
56 pevent_register_event_handler(pevent, -1, "kmem", "kmalloc",
57 call_site_handler, NULL);
58
59 pevent_register_event_handler(pevent, -1, "kmem", "kmalloc_node",
60 call_site_handler, NULL);
61
62 pevent_register_event_handler(pevent, -1, "kmem", "kmem_cache_alloc",
63 call_site_handler, NULL);
64
65 pevent_register_event_handler(pevent, -1, "kmem",
66 "kmem_cache_alloc_node",
67 call_site_handler, NULL);
68
69 pevent_register_event_handler(pevent, -1, "kmem", "kmem_cache_free",
70 call_site_handler, NULL);
71 return 0;
72}
diff --git a/tools/lib/traceevent/plugin_kvm.c b/tools/lib/traceevent/plugin_kvm.c
new file mode 100644
index 000000000000..a0e282c6b967
--- /dev/null
+++ b/tools/lib/traceevent/plugin_kvm.c
@@ -0,0 +1,436 @@
1/*
2 * Copyright (C) 2009 Red Hat Inc, Steven Rostedt <srostedt@redhat.com>
3 *
4 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation;
8 * version 2.1 of the License (not later!)
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this program; if not, see <http://www.gnu.org/licenses>
17 *
18 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
19 */
20#include <stdio.h>
21#include <stdlib.h>
22#include <string.h>
23#include <stdint.h>
24
25#include "event-parse.h"
26
27#ifdef HAVE_UDIS86
28
29#include <udis86.h>
30
31static ud_t ud;
32
33static void init_disassembler(void)
34{
35 ud_init(&ud);
36 ud_set_syntax(&ud, UD_SYN_ATT);
37}
38
39static const char *disassemble(unsigned char *insn, int len, uint64_t rip,
40 int cr0_pe, int eflags_vm,
41 int cs_d, int cs_l)
42{
43 int mode;
44
45 if (!cr0_pe)
46 mode = 16;
47 else if (eflags_vm)
48 mode = 16;
49 else if (cs_l)
50 mode = 64;
51 else if (cs_d)
52 mode = 32;
53 else
54 mode = 16;
55
56 ud_set_pc(&ud, rip);
57 ud_set_mode(&ud, mode);
58 ud_set_input_buffer(&ud, insn, len);
59 ud_disassemble(&ud);
60 return ud_insn_asm(&ud);
61}
62
63#else
64
65static void init_disassembler(void)
66{
67}
68
69static const char *disassemble(unsigned char *insn, int len, uint64_t rip,
70 int cr0_pe, int eflags_vm,
71 int cs_d, int cs_l)
72{
73 static char out[15*3+1];
74 int i;
75
76 for (i = 0; i < len; ++i)
77 sprintf(out + i * 3, "%02x ", insn[i]);
78 out[len*3-1] = '\0';
79 return out;
80}
81
82#endif
83
84
85#define VMX_EXIT_REASONS \
86 _ER(EXCEPTION_NMI, 0) \
87 _ER(EXTERNAL_INTERRUPT, 1) \
88 _ER(TRIPLE_FAULT, 2) \
89 _ER(PENDING_INTERRUPT, 7) \
90 _ER(NMI_WINDOW, 8) \
91 _ER(TASK_SWITCH, 9) \
92 _ER(CPUID, 10) \
93 _ER(HLT, 12) \
94 _ER(INVD, 13) \
95 _ER(INVLPG, 14) \
96 _ER(RDPMC, 15) \
97 _ER(RDTSC, 16) \
98 _ER(VMCALL, 18) \
99 _ER(VMCLEAR, 19) \
100 _ER(VMLAUNCH, 20) \
101 _ER(VMPTRLD, 21) \
102 _ER(VMPTRST, 22) \
103 _ER(VMREAD, 23) \
104 _ER(VMRESUME, 24) \
105 _ER(VMWRITE, 25) \
106 _ER(VMOFF, 26) \
107 _ER(VMON, 27) \
108 _ER(CR_ACCESS, 28) \
109 _ER(DR_ACCESS, 29) \
110 _ER(IO_INSTRUCTION, 30) \
111 _ER(MSR_READ, 31) \
112 _ER(MSR_WRITE, 32) \
113 _ER(MWAIT_INSTRUCTION, 36) \
114 _ER(MONITOR_INSTRUCTION, 39) \
115 _ER(PAUSE_INSTRUCTION, 40) \
116 _ER(MCE_DURING_VMENTRY, 41) \
117 _ER(TPR_BELOW_THRESHOLD, 43) \
118 _ER(APIC_ACCESS, 44) \
119 _ER(EOI_INDUCED, 45) \
120 _ER(EPT_VIOLATION, 48) \
121 _ER(EPT_MISCONFIG, 49) \
122 _ER(INVEPT, 50) \
123 _ER(PREEMPTION_TIMER, 52) \
124 _ER(WBINVD, 54) \
125 _ER(XSETBV, 55) \
126 _ER(APIC_WRITE, 56) \
127 _ER(INVPCID, 58)
128
129#define SVM_EXIT_REASONS \
130 _ER(EXIT_READ_CR0, 0x000) \
131 _ER(EXIT_READ_CR3, 0x003) \
132 _ER(EXIT_READ_CR4, 0x004) \
133 _ER(EXIT_READ_CR8, 0x008) \
134 _ER(EXIT_WRITE_CR0, 0x010) \
135 _ER(EXIT_WRITE_CR3, 0x013) \
136 _ER(EXIT_WRITE_CR4, 0x014) \
137 _ER(EXIT_WRITE_CR8, 0x018) \
138 _ER(EXIT_READ_DR0, 0x020) \
139 _ER(EXIT_READ_DR1, 0x021) \
140 _ER(EXIT_READ_DR2, 0x022) \
141 _ER(EXIT_READ_DR3, 0x023) \
142 _ER(EXIT_READ_DR4, 0x024) \
143 _ER(EXIT_READ_DR5, 0x025) \
144 _ER(EXIT_READ_DR6, 0x026) \
145 _ER(EXIT_READ_DR7, 0x027) \
146 _ER(EXIT_WRITE_DR0, 0x030) \
147 _ER(EXIT_WRITE_DR1, 0x031) \
148 _ER(EXIT_WRITE_DR2, 0x032) \
149 _ER(EXIT_WRITE_DR3, 0x033) \
150 _ER(EXIT_WRITE_DR4, 0x034) \
151 _ER(EXIT_WRITE_DR5, 0x035) \
152 _ER(EXIT_WRITE_DR6, 0x036) \
153 _ER(EXIT_WRITE_DR7, 0x037) \
154 _ER(EXIT_EXCP_BASE, 0x040) \
155 _ER(EXIT_INTR, 0x060) \
156 _ER(EXIT_NMI, 0x061) \
157 _ER(EXIT_SMI, 0x062) \
158 _ER(EXIT_INIT, 0x063) \
159 _ER(EXIT_VINTR, 0x064) \
160 _ER(EXIT_CR0_SEL_WRITE, 0x065) \
161 _ER(EXIT_IDTR_READ, 0x066) \
162 _ER(EXIT_GDTR_READ, 0x067) \
163 _ER(EXIT_LDTR_READ, 0x068) \
164 _ER(EXIT_TR_READ, 0x069) \
165 _ER(EXIT_IDTR_WRITE, 0x06a) \
166 _ER(EXIT_GDTR_WRITE, 0x06b) \
167 _ER(EXIT_LDTR_WRITE, 0x06c) \
168 _ER(EXIT_TR_WRITE, 0x06d) \
169 _ER(EXIT_RDTSC, 0x06e) \
170 _ER(EXIT_RDPMC, 0x06f) \
171 _ER(EXIT_PUSHF, 0x070) \
172 _ER(EXIT_POPF, 0x071) \
173 _ER(EXIT_CPUID, 0x072) \
174 _ER(EXIT_RSM, 0x073) \
175 _ER(EXIT_IRET, 0x074) \
176 _ER(EXIT_SWINT, 0x075) \
177 _ER(EXIT_INVD, 0x076) \
178 _ER(EXIT_PAUSE, 0x077) \
179 _ER(EXIT_HLT, 0x078) \
180 _ER(EXIT_INVLPG, 0x079) \
181 _ER(EXIT_INVLPGA, 0x07a) \
182 _ER(EXIT_IOIO, 0x07b) \
183 _ER(EXIT_MSR, 0x07c) \
184 _ER(EXIT_TASK_SWITCH, 0x07d) \
185 _ER(EXIT_FERR_FREEZE, 0x07e) \
186 _ER(EXIT_SHUTDOWN, 0x07f) \
187 _ER(EXIT_VMRUN, 0x080) \
188 _ER(EXIT_VMMCALL, 0x081) \
189 _ER(EXIT_VMLOAD, 0x082) \
190 _ER(EXIT_VMSAVE, 0x083) \
191 _ER(EXIT_STGI, 0x084) \
192 _ER(EXIT_CLGI, 0x085) \
193 _ER(EXIT_SKINIT, 0x086) \
194 _ER(EXIT_RDTSCP, 0x087) \
195 _ER(EXIT_ICEBP, 0x088) \
196 _ER(EXIT_WBINVD, 0x089) \
197 _ER(EXIT_MONITOR, 0x08a) \
198 _ER(EXIT_MWAIT, 0x08b) \
199 _ER(EXIT_MWAIT_COND, 0x08c) \
200 _ER(EXIT_NPF, 0x400) \
201 _ER(EXIT_ERR, -1)
202
203#define _ER(reason, val) { #reason, val },
204struct str_values {
205 const char *str;
206 int val;
207};
208
209static struct str_values vmx_exit_reasons[] = {
210 VMX_EXIT_REASONS
211 { NULL, -1}
212};
213
214static struct str_values svm_exit_reasons[] = {
215 SVM_EXIT_REASONS
216 { NULL, -1}
217};
218
219static struct isa_exit_reasons {
220 unsigned isa;
221 struct str_values *strings;
222} isa_exit_reasons[] = {
223 { .isa = 1, .strings = vmx_exit_reasons },
224 { .isa = 2, .strings = svm_exit_reasons },
225 { }
226};
227
228static const char *find_exit_reason(unsigned isa, int val)
229{
230 struct str_values *strings = NULL;
231 int i;
232
233 for (i = 0; isa_exit_reasons[i].strings; ++i)
234 if (isa_exit_reasons[i].isa == isa) {
235 strings = isa_exit_reasons[i].strings;
236 break;
237 }
238 if (!strings)
239 return "UNKNOWN-ISA";
240 for (i = 0; strings[i].val >= 0; i++)
241 if (strings[i].val == val)
242 break;
243 if (strings[i].str)
244 return strings[i].str;
245 return "UNKNOWN";
246}
247
248static int kvm_exit_handler(struct trace_seq *s, struct pevent_record *record,
249 struct event_format *event, void *context)
250{
251 unsigned long long isa;
252 unsigned long long val;
253 unsigned long long info1 = 0, info2 = 0;
254
255 if (pevent_get_field_val(s, event, "exit_reason", record, &val, 1) < 0)
256 return -1;
257
258 if (pevent_get_field_val(s, event, "isa", record, &isa, 0) < 0)
259 isa = 1;
260
261 trace_seq_printf(s, "reason %s", find_exit_reason(isa, val));
262
263 pevent_print_num_field(s, " rip 0x%lx", event, "guest_rip", record, 1);
264
265 if (pevent_get_field_val(s, event, "info1", record, &info1, 0) >= 0
266 && pevent_get_field_val(s, event, "info2", record, &info2, 0) >= 0)
267 trace_seq_printf(s, " info %llx %llx", info1, info2);
268
269 return 0;
270}
271
272#define KVM_EMUL_INSN_F_CR0_PE (1 << 0)
273#define KVM_EMUL_INSN_F_EFL_VM (1 << 1)
274#define KVM_EMUL_INSN_F_CS_D (1 << 2)
275#define KVM_EMUL_INSN_F_CS_L (1 << 3)
276
277static int kvm_emulate_insn_handler(struct trace_seq *s,
278 struct pevent_record *record,
279 struct event_format *event, void *context)
280{
281 unsigned long long rip, csbase, len, flags, failed;
282 int llen;
283 uint8_t *insn;
284 const char *disasm;
285
286 if (pevent_get_field_val(s, event, "rip", record, &rip, 1) < 0)
287 return -1;
288
289 if (pevent_get_field_val(s, event, "csbase", record, &csbase, 1) < 0)
290 return -1;
291
292 if (pevent_get_field_val(s, event, "len", record, &len, 1) < 0)
293 return -1;
294
295 if (pevent_get_field_val(s, event, "flags", record, &flags, 1) < 0)
296 return -1;
297
298 if (pevent_get_field_val(s, event, "failed", record, &failed, 1) < 0)
299 return -1;
300
301 insn = pevent_get_field_raw(s, event, "insn", record, &llen, 1);
302 if (!insn)
303 return -1;
304
305 disasm = disassemble(insn, len, rip,
306 flags & KVM_EMUL_INSN_F_CR0_PE,
307 flags & KVM_EMUL_INSN_F_EFL_VM,
308 flags & KVM_EMUL_INSN_F_CS_D,
309 flags & KVM_EMUL_INSN_F_CS_L);
310
311 trace_seq_printf(s, "%llx:%llx: %s%s", csbase, rip, disasm,
312 failed ? " FAIL" : "");
313 return 0;
314}
315
316union kvm_mmu_page_role {
317 unsigned word;
318 struct {
319 unsigned glevels:4;
320 unsigned level:4;
321 unsigned quadrant:2;
322 unsigned pad_for_nice_hex_output:6;
323 unsigned direct:1;
324 unsigned access:3;
325 unsigned invalid:1;
326 unsigned cr4_pge:1;
327 unsigned nxe:1;
328 };
329};
330
331static int kvm_mmu_print_role(struct trace_seq *s, struct pevent_record *record,
332 struct event_format *event, void *context)
333{
334 unsigned long long val;
335 static const char *access_str[] = {
336 "---", "--x", "w--", "w-x", "-u-", "-ux", "wu-", "wux"
337 };
338 union kvm_mmu_page_role role;
339
340 if (pevent_get_field_val(s, event, "role", record, &val, 1) < 0)
341 return -1;
342
343 role.word = (int)val;
344
345 /*
346 * We can only use the structure if file is of the same
347 * endianess.
348 */
349 if (pevent_is_file_bigendian(event->pevent) ==
350 pevent_is_host_bigendian(event->pevent)) {
351
352 trace_seq_printf(s, "%u/%u q%u%s %s%s %spge %snxe",
353 role.level,
354 role.glevels,
355 role.quadrant,
356 role.direct ? " direct" : "",
357 access_str[role.access],
358 role.invalid ? " invalid" : "",
359 role.cr4_pge ? "" : "!",
360 role.nxe ? "" : "!");
361 } else
362 trace_seq_printf(s, "WORD: %08x", role.word);
363
364 pevent_print_num_field(s, " root %u ", event,
365 "root_count", record, 1);
366
367 if (pevent_get_field_val(s, event, "unsync", record, &val, 1) < 0)
368 return -1;
369
370 trace_seq_printf(s, "%s%c", val ? "unsync" : "sync", 0);
371 return 0;
372}
373
374static int kvm_mmu_get_page_handler(struct trace_seq *s,
375 struct pevent_record *record,
376 struct event_format *event, void *context)
377{
378 unsigned long long val;
379
380 if (pevent_get_field_val(s, event, "created", record, &val, 1) < 0)
381 return -1;
382
383 trace_seq_printf(s, "%s ", val ? "new" : "existing");
384
385 if (pevent_get_field_val(s, event, "gfn", record, &val, 1) < 0)
386 return -1;
387
388 trace_seq_printf(s, "sp gfn %llx ", val);
389 return kvm_mmu_print_role(s, record, event, context);
390}
391
392#define PT_WRITABLE_SHIFT 1
393#define PT_WRITABLE_MASK (1ULL << PT_WRITABLE_SHIFT)
394
395static unsigned long long
396process_is_writable_pte(struct trace_seq *s, unsigned long long *args)
397{
398 unsigned long pte = args[0];
399 return pte & PT_WRITABLE_MASK;
400}
401
402int PEVENT_PLUGIN_LOADER(struct pevent *pevent)
403{
404 init_disassembler();
405
406 pevent_register_event_handler(pevent, -1, "kvm", "kvm_exit",
407 kvm_exit_handler, NULL);
408
409 pevent_register_event_handler(pevent, -1, "kvm", "kvm_emulate_insn",
410 kvm_emulate_insn_handler, NULL);
411
412 pevent_register_event_handler(pevent, -1, "kvmmmu", "kvm_mmu_get_page",
413 kvm_mmu_get_page_handler, NULL);
414
415 pevent_register_event_handler(pevent, -1, "kvmmmu", "kvm_mmu_sync_page",
416 kvm_mmu_print_role, NULL);
417
418 pevent_register_event_handler(pevent, -1,
419 "kvmmmu", "kvm_mmu_unsync_page",
420 kvm_mmu_print_role, NULL);
421
422 pevent_register_event_handler(pevent, -1, "kvmmmu", "kvm_mmu_zap_page",
423 kvm_mmu_print_role, NULL);
424
425 pevent_register_event_handler(pevent, -1, "kvmmmu",
426 "kvm_mmu_prepare_zap_page", kvm_mmu_print_role,
427 NULL);
428
429 pevent_register_print_function(pevent,
430 process_is_writable_pte,
431 PEVENT_FUNC_ARG_INT,
432 "is_writable_pte",
433 PEVENT_FUNC_ARG_LONG,
434 PEVENT_FUNC_ARG_VOID);
435 return 0;
436}
diff --git a/tools/lib/traceevent/plugin_mac80211.c b/tools/lib/traceevent/plugin_mac80211.c
new file mode 100644
index 000000000000..558a3b91c046
--- /dev/null
+++ b/tools/lib/traceevent/plugin_mac80211.c
@@ -0,0 +1,95 @@
1/*
2 * Copyright (C) 2009 Johannes Berg <johannes@sipsolutions.net>
3 *
4 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation;
8 * version 2.1 of the License (not later!)
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this program; if not, see <http://www.gnu.org/licenses>
17 *
18 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
19 */
20#include <stdio.h>
21#include <stdlib.h>
22#include <string.h>
23
24#include "event-parse.h"
25
26#define INDENT 65
27
28static void print_string(struct trace_seq *s, struct event_format *event,
29 const char *name, const void *data)
30{
31 struct format_field *f = pevent_find_field(event, name);
32 int offset;
33 int length;
34
35 if (!f) {
36 trace_seq_printf(s, "NOTFOUND:%s", name);
37 return;
38 }
39
40 offset = f->offset;
41 length = f->size;
42
43 if (!strncmp(f->type, "__data_loc", 10)) {
44 unsigned long long v;
45 if (pevent_read_number_field(f, data, &v)) {
46 trace_seq_printf(s, "invalid_data_loc");
47 return;
48 }
49 offset = v & 0xffff;
50 length = v >> 16;
51 }
52
53 trace_seq_printf(s, "%.*s", length, (char *)data + offset);
54}
55
56#define SF(fn) pevent_print_num_field(s, fn ":%d", event, fn, record, 0)
57#define SFX(fn) pevent_print_num_field(s, fn ":%#x", event, fn, record, 0)
58#define SP() trace_seq_putc(s, ' ')
59
60static int drv_bss_info_changed(struct trace_seq *s,
61 struct pevent_record *record,
62 struct event_format *event, void *context)
63{
64 void *data = record->data;
65
66 print_string(s, event, "wiphy_name", data);
67 trace_seq_printf(s, " vif:");
68 print_string(s, event, "vif_name", data);
69 pevent_print_num_field(s, "(%d)", event, "vif_type", record, 1);
70
71 trace_seq_printf(s, "\n%*s", INDENT, "");
72 SF("assoc"); SP();
73 SF("aid"); SP();
74 SF("cts"); SP();
75 SF("shortpre"); SP();
76 SF("shortslot"); SP();
77 SF("dtimper"); SP();
78 trace_seq_printf(s, "\n%*s", INDENT, "");
79 SF("bcnint"); SP();
80 SFX("assoc_cap"); SP();
81 SFX("basic_rates"); SP();
82 SF("enable_beacon");
83 trace_seq_printf(s, "\n%*s", INDENT, "");
84 SF("ht_operation_mode");
85
86 return 0;
87}
88
89int PEVENT_PLUGIN_LOADER(struct pevent *pevent)
90{
91 pevent_register_event_handler(pevent, -1, "mac80211",
92 "drv_bss_info_changed",
93 drv_bss_info_changed, NULL);
94 return 0;
95}
diff --git a/tools/lib/traceevent/plugin_sched_switch.c b/tools/lib/traceevent/plugin_sched_switch.c
new file mode 100644
index 000000000000..fea3724aa24f
--- /dev/null
+++ b/tools/lib/traceevent/plugin_sched_switch.c
@@ -0,0 +1,148 @@
1/*
2 * Copyright (C) 2009, 2010 Red Hat Inc, Steven Rostedt <srostedt@redhat.com>
3 *
4 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation;
8 * version 2.1 of the License (not later!)
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this program; if not, see <http://www.gnu.org/licenses>
17 *
18 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
19 */
20#include <stdio.h>
21#include <stdlib.h>
22#include <string.h>
23
24#include "event-parse.h"
25
26static void write_state(struct trace_seq *s, int val)
27{
28 const char states[] = "SDTtZXxW";
29 int found = 0;
30 int i;
31
32 for (i = 0; i < (sizeof(states) - 1); i++) {
33 if (!(val & (1 << i)))
34 continue;
35
36 if (found)
37 trace_seq_putc(s, '|');
38
39 found = 1;
40 trace_seq_putc(s, states[i]);
41 }
42
43 if (!found)
44 trace_seq_putc(s, 'R');
45}
46
47static void write_and_save_comm(struct format_field *field,
48 struct pevent_record *record,
49 struct trace_seq *s, int pid)
50{
51 const char *comm;
52 int len;
53
54 comm = (char *)(record->data + field->offset);
55 len = s->len;
56 trace_seq_printf(s, "%.*s",
57 field->size, comm);
58
59 /* make sure the comm has a \0 at the end. */
60 trace_seq_terminate(s);
61 comm = &s->buffer[len];
62
63 /* Help out the comm to ids. This will handle dups */
64 pevent_register_comm(field->event->pevent, comm, pid);
65}
66
67static int sched_wakeup_handler(struct trace_seq *s,
68 struct pevent_record *record,
69 struct event_format *event, void *context)
70{
71 struct format_field *field;
72 unsigned long long val;
73
74 if (pevent_get_field_val(s, event, "pid", record, &val, 1))
75 return trace_seq_putc(s, '!');
76
77 field = pevent_find_any_field(event, "comm");
78 if (field) {
79 write_and_save_comm(field, record, s, val);
80 trace_seq_putc(s, ':');
81 }
82 trace_seq_printf(s, "%lld", val);
83
84 if (pevent_get_field_val(s, event, "prio", record, &val, 0) == 0)
85 trace_seq_printf(s, " [%lld]", val);
86
87 if (pevent_get_field_val(s, event, "success", record, &val, 1) == 0)
88 trace_seq_printf(s, " success=%lld", val);
89
90 if (pevent_get_field_val(s, event, "target_cpu", record, &val, 0) == 0)
91 trace_seq_printf(s, " CPU:%03llu", val);
92
93 return 0;
94}
95
96static int sched_switch_handler(struct trace_seq *s,
97 struct pevent_record *record,
98 struct event_format *event, void *context)
99{
100 struct format_field *field;
101 unsigned long long val;
102
103 if (pevent_get_field_val(s, event, "prev_pid", record, &val, 1))
104 return trace_seq_putc(s, '!');
105
106 field = pevent_find_any_field(event, "prev_comm");
107 if (field) {
108 write_and_save_comm(field, record, s, val);
109 trace_seq_putc(s, ':');
110 }
111 trace_seq_printf(s, "%lld ", val);
112
113 if (pevent_get_field_val(s, event, "prev_prio", record, &val, 0) == 0)
114 trace_seq_printf(s, "[%lld] ", val);
115
116 if (pevent_get_field_val(s, event, "prev_state", record, &val, 0) == 0)
117 write_state(s, val);
118
119 trace_seq_puts(s, " ==> ");
120
121 if (pevent_get_field_val(s, event, "next_pid", record, &val, 1))
122 return trace_seq_putc(s, '!');
123
124 field = pevent_find_any_field(event, "next_comm");
125 if (field) {
126 write_and_save_comm(field, record, s, val);
127 trace_seq_putc(s, ':');
128 }
129 trace_seq_printf(s, "%lld", val);
130
131 if (pevent_get_field_val(s, event, "next_prio", record, &val, 0) == 0)
132 trace_seq_printf(s, " [%lld]", val);
133
134 return 0;
135}
136
137int PEVENT_PLUGIN_LOADER(struct pevent *pevent)
138{
139 pevent_register_event_handler(pevent, -1, "sched", "sched_switch",
140 sched_switch_handler, NULL);
141
142 pevent_register_event_handler(pevent, -1, "sched", "sched_wakeup",
143 sched_wakeup_handler, NULL);
144
145 pevent_register_event_handler(pevent, -1, "sched", "sched_wakeup_new",
146 sched_wakeup_handler, NULL);
147 return 0;
148}
diff --git a/tools/lib/traceevent/plugin_scsi.c b/tools/lib/traceevent/plugin_scsi.c
new file mode 100644
index 000000000000..6fb8e3e3fcad
--- /dev/null
+++ b/tools/lib/traceevent/plugin_scsi.c
@@ -0,0 +1,423 @@
1#include <stdio.h>
2#include <string.h>
3#include <inttypes.h>
4#include "event-parse.h"
5
6typedef unsigned long sector_t;
7typedef uint64_t u64;
8typedef unsigned int u32;
9
10/*
11 * SCSI opcodes
12 */
13#define TEST_UNIT_READY 0x00
14#define REZERO_UNIT 0x01
15#define REQUEST_SENSE 0x03
16#define FORMAT_UNIT 0x04
17#define READ_BLOCK_LIMITS 0x05
18#define REASSIGN_BLOCKS 0x07
19#define INITIALIZE_ELEMENT_STATUS 0x07
20#define READ_6 0x08
21#define WRITE_6 0x0a
22#define SEEK_6 0x0b
23#define READ_REVERSE 0x0f
24#define WRITE_FILEMARKS 0x10
25#define SPACE 0x11
26#define INQUIRY 0x12
27#define RECOVER_BUFFERED_DATA 0x14
28#define MODE_SELECT 0x15
29#define RESERVE 0x16
30#define RELEASE 0x17
31#define COPY 0x18
32#define ERASE 0x19
33#define MODE_SENSE 0x1a
34#define START_STOP 0x1b
35#define RECEIVE_DIAGNOSTIC 0x1c
36#define SEND_DIAGNOSTIC 0x1d
37#define ALLOW_MEDIUM_REMOVAL 0x1e
38
39#define READ_FORMAT_CAPACITIES 0x23
40#define SET_WINDOW 0x24
41#define READ_CAPACITY 0x25
42#define READ_10 0x28
43#define WRITE_10 0x2a
44#define SEEK_10 0x2b
45#define POSITION_TO_ELEMENT 0x2b
46#define WRITE_VERIFY 0x2e
47#define VERIFY 0x2f
48#define SEARCH_HIGH 0x30
49#define SEARCH_EQUAL 0x31
50#define SEARCH_LOW 0x32
51#define SET_LIMITS 0x33
52#define PRE_FETCH 0x34
53#define READ_POSITION 0x34
54#define SYNCHRONIZE_CACHE 0x35
55#define LOCK_UNLOCK_CACHE 0x36
56#define READ_DEFECT_DATA 0x37
57#define MEDIUM_SCAN 0x38
58#define COMPARE 0x39
59#define COPY_VERIFY 0x3a
60#define WRITE_BUFFER 0x3b
61#define READ_BUFFER 0x3c
62#define UPDATE_BLOCK 0x3d
63#define READ_LONG 0x3e
64#define WRITE_LONG 0x3f
65#define CHANGE_DEFINITION 0x40
66#define WRITE_SAME 0x41
67#define UNMAP 0x42
68#define READ_TOC 0x43
69#define READ_HEADER 0x44
70#define GET_EVENT_STATUS_NOTIFICATION 0x4a
71#define LOG_SELECT 0x4c
72#define LOG_SENSE 0x4d
73#define XDWRITEREAD_10 0x53
74#define MODE_SELECT_10 0x55
75#define RESERVE_10 0x56
76#define RELEASE_10 0x57
77#define MODE_SENSE_10 0x5a
78#define PERSISTENT_RESERVE_IN 0x5e
79#define PERSISTENT_RESERVE_OUT 0x5f
80#define VARIABLE_LENGTH_CMD 0x7f
81#define REPORT_LUNS 0xa0
82#define SECURITY_PROTOCOL_IN 0xa2
83#define MAINTENANCE_IN 0xa3
84#define MAINTENANCE_OUT 0xa4
85#define MOVE_MEDIUM 0xa5
86#define EXCHANGE_MEDIUM 0xa6
87#define READ_12 0xa8
88#define WRITE_12 0xaa
89#define READ_MEDIA_SERIAL_NUMBER 0xab
90#define WRITE_VERIFY_12 0xae
91#define VERIFY_12 0xaf
92#define SEARCH_HIGH_12 0xb0
93#define SEARCH_EQUAL_12 0xb1
94#define SEARCH_LOW_12 0xb2
95#define SECURITY_PROTOCOL_OUT 0xb5
96#define READ_ELEMENT_STATUS 0xb8
97#define SEND_VOLUME_TAG 0xb6
98#define WRITE_LONG_2 0xea
99#define EXTENDED_COPY 0x83
100#define RECEIVE_COPY_RESULTS 0x84
101#define ACCESS_CONTROL_IN 0x86
102#define ACCESS_CONTROL_OUT 0x87
103#define READ_16 0x88
104#define WRITE_16 0x8a
105#define READ_ATTRIBUTE 0x8c
106#define WRITE_ATTRIBUTE 0x8d
107#define VERIFY_16 0x8f
108#define SYNCHRONIZE_CACHE_16 0x91
109#define WRITE_SAME_16 0x93
110#define SERVICE_ACTION_IN 0x9e
111/* values for service action in */
112#define SAI_READ_CAPACITY_16 0x10
113#define SAI_GET_LBA_STATUS 0x12
114/* values for VARIABLE_LENGTH_CMD service action codes
115 * see spc4r17 Section D.3.5, table D.7 and D.8 */
116#define VLC_SA_RECEIVE_CREDENTIAL 0x1800
117/* values for maintenance in */
118#define MI_REPORT_IDENTIFYING_INFORMATION 0x05
119#define MI_REPORT_TARGET_PGS 0x0a
120#define MI_REPORT_ALIASES 0x0b
121#define MI_REPORT_SUPPORTED_OPERATION_CODES 0x0c
122#define MI_REPORT_SUPPORTED_TASK_MANAGEMENT_FUNCTIONS 0x0d
123#define MI_REPORT_PRIORITY 0x0e
124#define MI_REPORT_TIMESTAMP 0x0f
125#define MI_MANAGEMENT_PROTOCOL_IN 0x10
126/* value for MI_REPORT_TARGET_PGS ext header */
127#define MI_EXT_HDR_PARAM_FMT 0x20
128/* values for maintenance out */
129#define MO_SET_IDENTIFYING_INFORMATION 0x06
130#define MO_SET_TARGET_PGS 0x0a
131#define MO_CHANGE_ALIASES 0x0b
132#define MO_SET_PRIORITY 0x0e
133#define MO_SET_TIMESTAMP 0x0f
134#define MO_MANAGEMENT_PROTOCOL_OUT 0x10
135/* values for variable length command */
136#define XDREAD_32 0x03
137#define XDWRITE_32 0x04
138#define XPWRITE_32 0x06
139#define XDWRITEREAD_32 0x07
140#define READ_32 0x09
141#define VERIFY_32 0x0a
142#define WRITE_32 0x0b
143#define WRITE_SAME_32 0x0d
144
145#define SERVICE_ACTION16(cdb) (cdb[1] & 0x1f)
146#define SERVICE_ACTION32(cdb) ((cdb[8] << 8) | cdb[9])
147
148static const char *
149scsi_trace_misc(struct trace_seq *, unsigned char *, int);
150
151static const char *
152scsi_trace_rw6(struct trace_seq *p, unsigned char *cdb, int len)
153{
154 const char *ret = p->buffer + p->len;
155 sector_t lba = 0, txlen = 0;
156
157 lba |= ((cdb[1] & 0x1F) << 16);
158 lba |= (cdb[2] << 8);
159 lba |= cdb[3];
160 txlen = cdb[4];
161
162 trace_seq_printf(p, "lba=%llu txlen=%llu",
163 (unsigned long long)lba, (unsigned long long)txlen);
164 trace_seq_putc(p, 0);
165 return ret;
166}
167
168static const char *
169scsi_trace_rw10(struct trace_seq *p, unsigned char *cdb, int len)
170{
171 const char *ret = p->buffer + p->len;
172 sector_t lba = 0, txlen = 0;
173
174 lba |= (cdb[2] << 24);
175 lba |= (cdb[3] << 16);
176 lba |= (cdb[4] << 8);
177 lba |= cdb[5];
178 txlen |= (cdb[7] << 8);
179 txlen |= cdb[8];
180
181 trace_seq_printf(p, "lba=%llu txlen=%llu protect=%u",
182 (unsigned long long)lba, (unsigned long long)txlen,
183 cdb[1] >> 5);
184
185 if (cdb[0] == WRITE_SAME)
186 trace_seq_printf(p, " unmap=%u", cdb[1] >> 3 & 1);
187
188 trace_seq_putc(p, 0);
189 return ret;
190}
191
192static const char *
193scsi_trace_rw12(struct trace_seq *p, unsigned char *cdb, int len)
194{
195 const char *ret = p->buffer + p->len;
196 sector_t lba = 0, txlen = 0;
197
198 lba |= (cdb[2] << 24);
199 lba |= (cdb[3] << 16);
200 lba |= (cdb[4] << 8);
201 lba |= cdb[5];
202 txlen |= (cdb[6] << 24);
203 txlen |= (cdb[7] << 16);
204 txlen |= (cdb[8] << 8);
205 txlen |= cdb[9];
206
207 trace_seq_printf(p, "lba=%llu txlen=%llu protect=%u",
208 (unsigned long long)lba, (unsigned long long)txlen,
209 cdb[1] >> 5);
210 trace_seq_putc(p, 0);
211 return ret;
212}
213
214static const char *
215scsi_trace_rw16(struct trace_seq *p, unsigned char *cdb, int len)
216{
217 const char *ret = p->buffer + p->len;
218 sector_t lba = 0, txlen = 0;
219
220 lba |= ((u64)cdb[2] << 56);
221 lba |= ((u64)cdb[3] << 48);
222 lba |= ((u64)cdb[4] << 40);
223 lba |= ((u64)cdb[5] << 32);
224 lba |= (cdb[6] << 24);
225 lba |= (cdb[7] << 16);
226 lba |= (cdb[8] << 8);
227 lba |= cdb[9];
228 txlen |= (cdb[10] << 24);
229 txlen |= (cdb[11] << 16);
230 txlen |= (cdb[12] << 8);
231 txlen |= cdb[13];
232
233 trace_seq_printf(p, "lba=%llu txlen=%llu protect=%u",
234 (unsigned long long)lba, (unsigned long long)txlen,
235 cdb[1] >> 5);
236
237 if (cdb[0] == WRITE_SAME_16)
238 trace_seq_printf(p, " unmap=%u", cdb[1] >> 3 & 1);
239
240 trace_seq_putc(p, 0);
241 return ret;
242}
243
244static const char *
245scsi_trace_rw32(struct trace_seq *p, unsigned char *cdb, int len)
246{
247 const char *ret = p->buffer + p->len, *cmd;
248 sector_t lba = 0, txlen = 0;
249 u32 ei_lbrt = 0;
250
251 switch (SERVICE_ACTION32(cdb)) {
252 case READ_32:
253 cmd = "READ";
254 break;
255 case VERIFY_32:
256 cmd = "VERIFY";
257 break;
258 case WRITE_32:
259 cmd = "WRITE";
260 break;
261 case WRITE_SAME_32:
262 cmd = "WRITE_SAME";
263 break;
264 default:
265 trace_seq_printf(p, "UNKNOWN");
266 goto out;
267 }
268
269 lba |= ((u64)cdb[12] << 56);
270 lba |= ((u64)cdb[13] << 48);
271 lba |= ((u64)cdb[14] << 40);
272 lba |= ((u64)cdb[15] << 32);
273 lba |= (cdb[16] << 24);
274 lba |= (cdb[17] << 16);
275 lba |= (cdb[18] << 8);
276 lba |= cdb[19];
277 ei_lbrt |= (cdb[20] << 24);
278 ei_lbrt |= (cdb[21] << 16);
279 ei_lbrt |= (cdb[22] << 8);
280 ei_lbrt |= cdb[23];
281 txlen |= (cdb[28] << 24);
282 txlen |= (cdb[29] << 16);
283 txlen |= (cdb[30] << 8);
284 txlen |= cdb[31];
285
286 trace_seq_printf(p, "%s_32 lba=%llu txlen=%llu protect=%u ei_lbrt=%u",
287 cmd, (unsigned long long)lba,
288 (unsigned long long)txlen, cdb[10] >> 5, ei_lbrt);
289
290 if (SERVICE_ACTION32(cdb) == WRITE_SAME_32)
291 trace_seq_printf(p, " unmap=%u", cdb[10] >> 3 & 1);
292
293out:
294 trace_seq_putc(p, 0);
295 return ret;
296}
297
298static const char *
299scsi_trace_unmap(struct trace_seq *p, unsigned char *cdb, int len)
300{
301 const char *ret = p->buffer + p->len;
302 unsigned int regions = cdb[7] << 8 | cdb[8];
303
304 trace_seq_printf(p, "regions=%u", (regions - 8) / 16);
305 trace_seq_putc(p, 0);
306 return ret;
307}
308
309static const char *
310scsi_trace_service_action_in(struct trace_seq *p, unsigned char *cdb, int len)
311{
312 const char *ret = p->buffer + p->len, *cmd;
313 sector_t lba = 0;
314 u32 alloc_len = 0;
315
316 switch (SERVICE_ACTION16(cdb)) {
317 case SAI_READ_CAPACITY_16:
318 cmd = "READ_CAPACITY_16";
319 break;
320 case SAI_GET_LBA_STATUS:
321 cmd = "GET_LBA_STATUS";
322 break;
323 default:
324 trace_seq_printf(p, "UNKNOWN");
325 goto out;
326 }
327
328 lba |= ((u64)cdb[2] << 56);
329 lba |= ((u64)cdb[3] << 48);
330 lba |= ((u64)cdb[4] << 40);
331 lba |= ((u64)cdb[5] << 32);
332 lba |= (cdb[6] << 24);
333 lba |= (cdb[7] << 16);
334 lba |= (cdb[8] << 8);
335 lba |= cdb[9];
336 alloc_len |= (cdb[10] << 24);
337 alloc_len |= (cdb[11] << 16);
338 alloc_len |= (cdb[12] << 8);
339 alloc_len |= cdb[13];
340
341 trace_seq_printf(p, "%s lba=%llu alloc_len=%u", cmd,
342 (unsigned long long)lba, alloc_len);
343
344out:
345 trace_seq_putc(p, 0);
346 return ret;
347}
348
349static const char *
350scsi_trace_varlen(struct trace_seq *p, unsigned char *cdb, int len)
351{
352 switch (SERVICE_ACTION32(cdb)) {
353 case READ_32:
354 case VERIFY_32:
355 case WRITE_32:
356 case WRITE_SAME_32:
357 return scsi_trace_rw32(p, cdb, len);
358 default:
359 return scsi_trace_misc(p, cdb, len);
360 }
361}
362
363static const char *
364scsi_trace_misc(struct trace_seq *p, unsigned char *cdb, int len)
365{
366 const char *ret = p->buffer + p->len;
367
368 trace_seq_printf(p, "-");
369 trace_seq_putc(p, 0);
370 return ret;
371}
372
373const char *
374scsi_trace_parse_cdb(struct trace_seq *p, unsigned char *cdb, int len)
375{
376 switch (cdb[0]) {
377 case READ_6:
378 case WRITE_6:
379 return scsi_trace_rw6(p, cdb, len);
380 case READ_10:
381 case VERIFY:
382 case WRITE_10:
383 case WRITE_SAME:
384 return scsi_trace_rw10(p, cdb, len);
385 case READ_12:
386 case VERIFY_12:
387 case WRITE_12:
388 return scsi_trace_rw12(p, cdb, len);
389 case READ_16:
390 case VERIFY_16:
391 case WRITE_16:
392 case WRITE_SAME_16:
393 return scsi_trace_rw16(p, cdb, len);
394 case UNMAP:
395 return scsi_trace_unmap(p, cdb, len);
396 case SERVICE_ACTION_IN:
397 return scsi_trace_service_action_in(p, cdb, len);
398 case VARIABLE_LENGTH_CMD:
399 return scsi_trace_varlen(p, cdb, len);
400 default:
401 return scsi_trace_misc(p, cdb, len);
402 }
403}
404
405unsigned long long process_scsi_trace_parse_cdb(struct trace_seq *s,
406 unsigned long long *args)
407{
408 scsi_trace_parse_cdb(s, (unsigned char *) args[1], args[2]);
409 return 0;
410}
411
412int PEVENT_PLUGIN_LOADER(struct pevent *pevent)
413{
414 pevent_register_print_function(pevent,
415 process_scsi_trace_parse_cdb,
416 PEVENT_FUNC_ARG_STRING,
417 "scsi_trace_parse_cdb",
418 PEVENT_FUNC_ARG_PTR,
419 PEVENT_FUNC_ARG_PTR,
420 PEVENT_FUNC_ARG_INT,
421 PEVENT_FUNC_ARG_VOID);
422 return 0;
423}
diff --git a/tools/lib/traceevent/plugin_xen.c b/tools/lib/traceevent/plugin_xen.c
new file mode 100644
index 000000000000..e7794298f3a9
--- /dev/null
+++ b/tools/lib/traceevent/plugin_xen.c
@@ -0,0 +1,130 @@
1#include <stdio.h>
2#include <stdlib.h>
3#include <string.h>
4#include "event-parse.h"
5
6#define __HYPERVISOR_set_trap_table 0
7#define __HYPERVISOR_mmu_update 1
8#define __HYPERVISOR_set_gdt 2
9#define __HYPERVISOR_stack_switch 3
10#define __HYPERVISOR_set_callbacks 4
11#define __HYPERVISOR_fpu_taskswitch 5
12#define __HYPERVISOR_sched_op_compat 6
13#define __HYPERVISOR_dom0_op 7
14#define __HYPERVISOR_set_debugreg 8
15#define __HYPERVISOR_get_debugreg 9
16#define __HYPERVISOR_update_descriptor 10
17#define __HYPERVISOR_memory_op 12
18#define __HYPERVISOR_multicall 13
19#define __HYPERVISOR_update_va_mapping 14
20#define __HYPERVISOR_set_timer_op 15
21#define __HYPERVISOR_event_channel_op_compat 16
22#define __HYPERVISOR_xen_version 17
23#define __HYPERVISOR_console_io 18
24#define __HYPERVISOR_physdev_op_compat 19
25#define __HYPERVISOR_grant_table_op 20
26#define __HYPERVISOR_vm_assist 21
27#define __HYPERVISOR_update_va_mapping_otherdomain 22
28#define __HYPERVISOR_iret 23 /* x86 only */
29#define __HYPERVISOR_vcpu_op 24
30#define __HYPERVISOR_set_segment_base 25 /* x86/64 only */
31#define __HYPERVISOR_mmuext_op 26
32#define __HYPERVISOR_acm_op 27
33#define __HYPERVISOR_nmi_op 28
34#define __HYPERVISOR_sched_op 29
35#define __HYPERVISOR_callback_op 30
36#define __HYPERVISOR_xenoprof_op 31
37#define __HYPERVISOR_event_channel_op 32
38#define __HYPERVISOR_physdev_op 33
39#define __HYPERVISOR_hvm_op 34
40#define __HYPERVISOR_tmem_op 38
41
42/* Architecture-specific hypercall definitions. */
43#define __HYPERVISOR_arch_0 48
44#define __HYPERVISOR_arch_1 49
45#define __HYPERVISOR_arch_2 50
46#define __HYPERVISOR_arch_3 51
47#define __HYPERVISOR_arch_4 52
48#define __HYPERVISOR_arch_5 53
49#define __HYPERVISOR_arch_6 54
50#define __HYPERVISOR_arch_7 55
51
52#define N(x) [__HYPERVISOR_##x] = "("#x")"
53static const char *xen_hypercall_names[] = {
54 N(set_trap_table),
55 N(mmu_update),
56 N(set_gdt),
57 N(stack_switch),
58 N(set_callbacks),
59 N(fpu_taskswitch),
60 N(sched_op_compat),
61 N(dom0_op),
62 N(set_debugreg),
63 N(get_debugreg),
64 N(update_descriptor),
65 N(memory_op),
66 N(multicall),
67 N(update_va_mapping),
68 N(set_timer_op),
69 N(event_channel_op_compat),
70 N(xen_version),
71 N(console_io),
72 N(physdev_op_compat),
73 N(grant_table_op),
74 N(vm_assist),
75 N(update_va_mapping_otherdomain),
76 N(iret),
77 N(vcpu_op),
78 N(set_segment_base),
79 N(mmuext_op),
80 N(acm_op),
81 N(nmi_op),
82 N(sched_op),
83 N(callback_op),
84 N(xenoprof_op),
85 N(event_channel_op),
86 N(physdev_op),
87 N(hvm_op),
88
89/* Architecture-specific hypercall definitions. */
90 N(arch_0),
91 N(arch_1),
92 N(arch_2),
93 N(arch_3),
94 N(arch_4),
95 N(arch_5),
96 N(arch_6),
97 N(arch_7),
98};
99#undef N
100
101#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
102
103static const char *xen_hypercall_name(unsigned op)
104{
105 if (op < ARRAY_SIZE(xen_hypercall_names) &&
106 xen_hypercall_names[op] != NULL)
107 return xen_hypercall_names[op];
108
109 return "";
110}
111
112unsigned long long process_xen_hypercall_name(struct trace_seq *s,
113 unsigned long long *args)
114{
115 unsigned int op = args[0];
116
117 trace_seq_printf(s, "%s", xen_hypercall_name(op));
118 return 0;
119}
120
121int PEVENT_PLUGIN_LOADER(struct pevent *pevent)
122{
123 pevent_register_print_function(pevent,
124 process_xen_hypercall_name,
125 PEVENT_FUNC_ARG_STRING,
126 "xen_hypercall_name",
127 PEVENT_FUNC_ARG_INT,
128 PEVENT_FUNC_ARG_VOID);
129 return 0;
130}
diff --git a/tools/perf/Documentation/perf-kvm.txt b/tools/perf/Documentation/perf-kvm.txt
index 6a06cefe9642..96a9a1dea727 100644
--- a/tools/perf/Documentation/perf-kvm.txt
+++ b/tools/perf/Documentation/perf-kvm.txt
@@ -24,10 +24,17 @@ There are a couple of variants of perf kvm:
24 of an arbitrary workload. 24 of an arbitrary workload.
25 25
26 'perf kvm record <command>' to record the performance counter profile 26 'perf kvm record <command>' to record the performance counter profile
27 of an arbitrary workload and save it into a perf data file. If both 27 of an arbitrary workload and save it into a perf data file. We set the
28 --host and --guest are input, the perf data file name is perf.data.kvm. 28 default behavior of perf kvm as --guest, so if neither --host nor --guest
29 If there is no --host but --guest, the file name is perf.data.guest. 29 is input, the perf data file name is perf.data.guest. If --host is input,
30 If there is no --guest but --host, the file name is perf.data.host. 30 the perf data file name is perf.data.kvm. If you want to record data into
31 perf.data.host, please input --host --no-guest. The behaviors are shown as
32 following:
33 Default('') -> perf.data.guest
34 --host -> perf.data.kvm
35 --guest -> perf.data.guest
36 --host --guest -> perf.data.kvm
37 --host --no-guest -> perf.data.host
31 38
32 'perf kvm report' to display the performance counter profile information 39 'perf kvm report' to display the performance counter profile information
33 recorded via perf kvm record. 40 recorded via perf kvm record.
@@ -37,7 +44,9 @@ There are a couple of variants of perf kvm:
37 44
38 'perf kvm buildid-list' to display the buildids found in a perf data file, 45 'perf kvm buildid-list' to display the buildids found in a perf data file,
39 so that other tools can be used to fetch packages with matching symbol tables 46 so that other tools can be used to fetch packages with matching symbol tables
40 for use by perf report. 47 for use by perf report. As buildid is read from /sys/kernel/notes in os, then
48 if you want to list the buildid for guest, please make sure your perf data file
49 was captured with --guestmount in perf kvm record.
41 50
42 'perf kvm stat <command>' to run a command and gather performance counter 51 'perf kvm stat <command>' to run a command and gather performance counter
43 statistics. 52 statistics.
@@ -58,14 +67,14 @@ There are a couple of variants of perf kvm:
58OPTIONS 67OPTIONS
59------- 68-------
60-i:: 69-i::
61--input=:: 70--input=<path>::
62 Input file name. 71 Input file name.
63-o:: 72-o::
64--output:: 73--output=<path>::
65 Output file name. 74 Output file name.
66--host=:: 75--host::
67 Collect host side performance profile. 76 Collect host side performance profile.
68--guest=:: 77--guest::
69 Collect guest side performance profile. 78 Collect guest side performance profile.
70--guestmount=<path>:: 79--guestmount=<path>::
71 Guest os root file system mount directory. Users mounts guest os 80 Guest os root file system mount directory. Users mounts guest os
diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
index e416ccc7d831..ca3b87d5389a 100644
--- a/tools/perf/Makefile.perf
+++ b/tools/perf/Makefile.perf
@@ -105,7 +105,7 @@ ifeq ($(config),1)
105include config/Makefile 105include config/Makefile
106endif 106endif
107 107
108export prefix bindir sharedir sysconfdir 108export prefix bindir sharedir sysconfdir DESTDIR
109 109
110# sparse is architecture-neutral, which means that we need to tell it 110# sparse is architecture-neutral, which means that we need to tell it
111# explicitly what architecture to check for. Fix this up for yours.. 111# explicitly what architecture to check for. Fix this up for yours..
@@ -353,6 +353,7 @@ LIB_OBJS += $(OUTPUT)util/pmu-bison.o
353LIB_OBJS += $(OUTPUT)util/trace-event-read.o 353LIB_OBJS += $(OUTPUT)util/trace-event-read.o
354LIB_OBJS += $(OUTPUT)util/trace-event-info.o 354LIB_OBJS += $(OUTPUT)util/trace-event-info.o
355LIB_OBJS += $(OUTPUT)util/trace-event-scripting.o 355LIB_OBJS += $(OUTPUT)util/trace-event-scripting.o
356LIB_OBJS += $(OUTPUT)util/trace-event.o
356LIB_OBJS += $(OUTPUT)util/svghelper.o 357LIB_OBJS += $(OUTPUT)util/svghelper.o
357LIB_OBJS += $(OUTPUT)util/sort.o 358LIB_OBJS += $(OUTPUT)util/sort.o
358LIB_OBJS += $(OUTPUT)util/hist.o 359LIB_OBJS += $(OUTPUT)util/hist.o
@@ -710,13 +711,20 @@ $(LIB_FILE): $(LIB_OBJS)
710# libtraceevent.a 711# libtraceevent.a
711TE_SOURCES = $(wildcard $(TRACE_EVENT_DIR)*.[ch]) 712TE_SOURCES = $(wildcard $(TRACE_EVENT_DIR)*.[ch])
712 713
713$(LIBTRACEEVENT): $(TE_SOURCES) 714LIBTRACEEVENT_FLAGS = $(QUIET_SUBDIR1) O=$(OUTPUT)
714 $(QUIET_SUBDIR0)$(TRACE_EVENT_DIR) $(QUIET_SUBDIR1) O=$(OUTPUT) CFLAGS="-g -Wall $(EXTRA_CFLAGS)" libtraceevent.a 715LIBTRACEEVENT_FLAGS += CFLAGS="-g -Wall $(EXTRA_CFLAGS)"
716LIBTRACEEVENT_FLAGS += plugin_dir=$(plugindir_SQ)
717
718$(LIBTRACEEVENT): $(TE_SOURCES) $(OUTPUT)PERF-CFLAGS
719 $(QUIET_SUBDIR0)$(TRACE_EVENT_DIR) $(LIBTRACEEVENT_FLAGS) libtraceevent.a plugins
715 720
716$(LIBTRACEEVENT)-clean: 721$(LIBTRACEEVENT)-clean:
717 $(call QUIET_CLEAN, libtraceevent) 722 $(call QUIET_CLEAN, libtraceevent)
718 @$(MAKE) -C $(TRACE_EVENT_DIR) O=$(OUTPUT) clean >/dev/null 723 @$(MAKE) -C $(TRACE_EVENT_DIR) O=$(OUTPUT) clean >/dev/null
719 724
725install-traceevent-plugins:
726 $(QUIET_SUBDIR0)$(TRACE_EVENT_DIR) $(LIBTRACEEVENT_FLAGS) install_plugins
727
720LIBLK_SOURCES = $(wildcard $(LK_PATH)*.[ch]) 728LIBLK_SOURCES = $(wildcard $(LK_PATH)*.[ch])
721 729
722# if subdir is set, we've been called from above so target has been built 730# if subdir is set, we've been called from above so target has been built
@@ -785,7 +793,7 @@ cscope:
785 793
786### Detect prefix changes 794### Detect prefix changes
787TRACK_CFLAGS = $(subst ','\'',$(CFLAGS)):\ 795TRACK_CFLAGS = $(subst ','\'',$(CFLAGS)):\
788 $(bindir_SQ):$(perfexecdir_SQ):$(template_dir_SQ):$(prefix_SQ) 796 $(bindir_SQ):$(perfexecdir_SQ):$(template_dir_SQ):$(prefix_SQ):$(plugindir_SQ)
789 797
790$(OUTPUT)PERF-CFLAGS: .FORCE-PERF-CFLAGS 798$(OUTPUT)PERF-CFLAGS: .FORCE-PERF-CFLAGS
791 @FLAGS='$(TRACK_CFLAGS)'; \ 799 @FLAGS='$(TRACK_CFLAGS)'; \
@@ -849,7 +857,7 @@ endif
849 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests/attr'; \ 857 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests/attr'; \
850 $(INSTALL) tests/attr/* '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests/attr' 858 $(INSTALL) tests/attr/* '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests/attr'
851 859
852install: install-bin try-install-man 860install: install-bin try-install-man install-traceevent-plugins
853 861
854install-python_ext: 862install-python_ext:
855 $(PYTHON_WORD) util/setup.py --quiet install --root='/$(DESTDIR_SQ)' 863 $(PYTHON_WORD) util/setup.py --quiet install --root='/$(DESTDIR_SQ)'
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index 952dce979252..4484886dcf08 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -414,7 +414,8 @@ static void print_sample_bts(union perf_event *event,
414 struct perf_sample *sample, 414 struct perf_sample *sample,
415 struct perf_evsel *evsel, 415 struct perf_evsel *evsel,
416 struct machine *machine, 416 struct machine *machine,
417 struct thread *thread) 417 struct thread *thread,
418 struct addr_location *al)
418{ 419{
419 struct perf_event_attr *attr = &evsel->attr; 420 struct perf_event_attr *attr = &evsel->attr;
420 421
@@ -424,7 +425,7 @@ static void print_sample_bts(union perf_event *event,
424 printf(" "); 425 printf(" ");
425 else 426 else
426 printf("\n"); 427 printf("\n");
427 perf_evsel__print_ip(evsel, event, sample, machine, 428 perf_evsel__print_ip(evsel, sample, machine, al,
428 output[attr->type].print_ip_opts, 429 output[attr->type].print_ip_opts,
429 PERF_MAX_STACK_DEPTH); 430 PERF_MAX_STACK_DEPTH);
430 } 431 }
@@ -443,7 +444,7 @@ static void print_sample_bts(union perf_event *event,
443static void process_event(union perf_event *event, struct perf_sample *sample, 444static void process_event(union perf_event *event, struct perf_sample *sample,
444 struct perf_evsel *evsel, struct machine *machine, 445 struct perf_evsel *evsel, struct machine *machine,
445 struct thread *thread, 446 struct thread *thread,
446 struct addr_location *al __maybe_unused) 447 struct addr_location *al)
447{ 448{
448 struct perf_event_attr *attr = &evsel->attr; 449 struct perf_event_attr *attr = &evsel->attr;
449 450
@@ -458,7 +459,7 @@ static void process_event(union perf_event *event, struct perf_sample *sample,
458 } 459 }
459 460
460 if (is_bts_event(attr)) { 461 if (is_bts_event(attr)) {
461 print_sample_bts(event, sample, evsel, machine, thread); 462 print_sample_bts(event, sample, evsel, machine, thread, al);
462 return; 463 return;
463 } 464 }
464 465
@@ -474,7 +475,7 @@ static void process_event(union perf_event *event, struct perf_sample *sample,
474 else 475 else
475 printf("\n"); 476 printf("\n");
476 477
477 perf_evsel__print_ip(evsel, event, sample, machine, 478 perf_evsel__print_ip(evsel, sample, machine, al,
478 output[attr->type].print_ip_opts, 479 output[attr->type].print_ip_opts,
479 PERF_MAX_STACK_DEPTH); 480 PERF_MAX_STACK_DEPTH);
480 } 481 }
@@ -1785,7 +1786,7 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
1785 return -1; 1786 return -1;
1786 } 1787 }
1787 1788
1788 err = scripting_ops->generate_script(session->pevent, 1789 err = scripting_ops->generate_script(session->tevent.pevent,
1789 "perf-script"); 1790 "perf-script");
1790 goto out; 1791 goto out;
1791 } 1792 }
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index 9f2a242fa79c..56afe339661a 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -11,6 +11,7 @@
11#include "util/intlist.h" 11#include "util/intlist.h"
12#include "util/thread_map.h" 12#include "util/thread_map.h"
13#include "util/stat.h" 13#include "util/stat.h"
14#include "trace-event.h"
14 15
15#include <libaudit.h> 16#include <libaudit.h>
16#include <stdlib.h> 17#include <stdlib.h>
@@ -1430,11 +1431,11 @@ static int trace__read_syscall_info(struct trace *trace, int id)
1430 sc->fmt = syscall_fmt__find(sc->name); 1431 sc->fmt = syscall_fmt__find(sc->name);
1431 1432
1432 snprintf(tp_name, sizeof(tp_name), "sys_enter_%s", sc->name); 1433 snprintf(tp_name, sizeof(tp_name), "sys_enter_%s", sc->name);
1433 sc->tp_format = event_format__new("syscalls", tp_name); 1434 sc->tp_format = trace_event__tp_format("syscalls", tp_name);
1434 1435
1435 if (sc->tp_format == NULL && sc->fmt && sc->fmt->alias) { 1436 if (sc->tp_format == NULL && sc->fmt && sc->fmt->alias) {
1436 snprintf(tp_name, sizeof(tp_name), "sys_enter_%s", sc->fmt->alias); 1437 snprintf(tp_name, sizeof(tp_name), "sys_enter_%s", sc->fmt->alias);
1437 sc->tp_format = event_format__new("syscalls", tp_name); 1438 sc->tp_format = trace_event__tp_format("syscalls", tp_name);
1438 } 1439 }
1439 1440
1440 if (sc->tp_format == NULL) 1441 if (sc->tp_format == NULL)
diff --git a/tools/perf/config/Makefile b/tools/perf/config/Makefile
index 36e66ac40abc..bae10720a136 100644
--- a/tools/perf/config/Makefile
+++ b/tools/perf/config/Makefile
@@ -141,7 +141,6 @@ CORE_FEATURE_TESTS = \
141 libslang \ 141 libslang \
142 libunwind \ 142 libunwind \
143 on-exit \ 143 on-exit \
144 stackprotector \
145 stackprotector-all \ 144 stackprotector-all \
146 timerfd 145 timerfd
147 146
@@ -209,10 +208,6 @@ ifeq ($(feature-stackprotector-all), 1)
209 CFLAGS += -fstack-protector-all 208 CFLAGS += -fstack-protector-all
210endif 209endif
211 210
212ifeq ($(feature-stackprotector), 1)
213 CFLAGS += -Wstack-protector
214endif
215
216ifeq ($(DEBUG),0) 211ifeq ($(DEBUG),0)
217 ifeq ($(feature-fortify-source), 1) 212 ifeq ($(feature-fortify-source), 1)
218 CFLAGS += -D_FORTIFY_SOURCE=2 213 CFLAGS += -D_FORTIFY_SOURCE=2
@@ -598,3 +593,11 @@ else
598perfexec_instdir = $(prefix)/$(perfexecdir) 593perfexec_instdir = $(prefix)/$(perfexecdir)
599endif 594endif
600perfexec_instdir_SQ = $(subst ','\'',$(perfexec_instdir)) 595perfexec_instdir_SQ = $(subst ','\'',$(perfexec_instdir))
596
597# If we install to $(HOME) we keep the traceevent default:
598# $(HOME)/.traceevent/plugins
599# Otherwise we install plugins into the global $(libdir).
600ifdef DESTDIR
601plugindir=$(libdir)/traceevent/plugins
602plugindir_SQ= $(subst ','\'',$(prefix)/$(plugindir))
603endif
diff --git a/tools/perf/config/feature-checks/Makefile b/tools/perf/config/feature-checks/Makefile
index 87e790017c69..b8bb749c3392 100644
--- a/tools/perf/config/feature-checks/Makefile
+++ b/tools/perf/config/feature-checks/Makefile
@@ -26,7 +26,6 @@ FILES= \
26 test-libunwind-debug-frame \ 26 test-libunwind-debug-frame \
27 test-on-exit \ 27 test-on-exit \
28 test-stackprotector-all \ 28 test-stackprotector-all \
29 test-stackprotector \
30 test-timerfd 29 test-timerfd
31 30
32CC := $(CC) -MD 31CC := $(CC) -MD
@@ -38,7 +37,7 @@ BUILD = $(CC) $(CFLAGS) $(LDFLAGS) -o $(OUTPUT)$@ $@.c
38############################### 37###############################
39 38
40test-all: 39test-all:
41 $(BUILD) -Werror -fstack-protector -fstack-protector-all -O2 -Werror -D_FORTIFY_SOURCE=2 -ldw -lelf -lnuma $(LIBUNWIND_LIBS) -lelf -laudit -I/usr/include/slang -lslang $(shell pkg-config --libs --cflags gtk+-2.0 2>/dev/null) $(FLAGS_PERL_EMBED) $(FLAGS_PYTHON_EMBED) -DPACKAGE='"perf"' -lbfd -ldl 40 $(BUILD) -Werror -fstack-protector-all -O2 -Werror -D_FORTIFY_SOURCE=2 -ldw -lelf -lnuma $(LIBUNWIND_LIBS) -lelf -laudit -I/usr/include/slang -lslang $(shell pkg-config --libs --cflags gtk+-2.0 2>/dev/null) $(FLAGS_PERL_EMBED) $(FLAGS_PYTHON_EMBED) -DPACKAGE='"perf"' -lbfd -ldl
42 41
43test-hello: 42test-hello:
44 $(BUILD) 43 $(BUILD)
@@ -46,9 +45,6 @@ test-hello:
46test-stackprotector-all: 45test-stackprotector-all:
47 $(BUILD) -Werror -fstack-protector-all 46 $(BUILD) -Werror -fstack-protector-all
48 47
49test-stackprotector:
50 $(BUILD) -Werror -fstack-protector -Wstack-protector
51
52test-fortify-source: 48test-fortify-source:
53 $(BUILD) -O2 -Werror -D_FORTIFY_SOURCE=2 49 $(BUILD) -O2 -Werror -D_FORTIFY_SOURCE=2
54 50
diff --git a/tools/perf/config/feature-checks/test-stackprotector.c b/tools/perf/config/feature-checks/test-stackprotector.c
deleted file mode 100644
index c9f398d87868..000000000000
--- a/tools/perf/config/feature-checks/test-stackprotector.c
+++ /dev/null
@@ -1,6 +0,0 @@
1#include <stdio.h>
2
3int main(void)
4{
5 return puts("hi");
6}
diff --git a/tools/perf/util/debug.c b/tools/perf/util/debug.c
index 399e74c34c1a..8640a9121e72 100644
--- a/tools/perf/util/debug.c
+++ b/tools/perf/util/debug.c
@@ -16,13 +16,11 @@
16int verbose; 16int verbose;
17bool dump_trace = false, quiet = false; 17bool dump_trace = false, quiet = false;
18 18
19int eprintf(int level, const char *fmt, ...) 19static int _eprintf(int level, const char *fmt, va_list args)
20{ 20{
21 va_list args;
22 int ret = 0; 21 int ret = 0;
23 22
24 if (verbose >= level) { 23 if (verbose >= level) {
25 va_start(args, fmt);
26 if (use_browser >= 1) 24 if (use_browser >= 1)
27 ui_helpline__vshow(fmt, args); 25 ui_helpline__vshow(fmt, args);
28 else 26 else
@@ -33,6 +31,32 @@ int eprintf(int level, const char *fmt, ...)
33 return ret; 31 return ret;
34} 32}
35 33
34int eprintf(int level, const char *fmt, ...)
35{
36 va_list args;
37 int ret;
38
39 va_start(args, fmt);
40 ret = _eprintf(level, fmt, args);
41 va_end(args);
42
43 return ret;
44}
45
46/*
47 * Overloading libtraceevent standard info print
48 * function, display with -v in perf.
49 */
50void pr_stat(const char *fmt, ...)
51{
52 va_list args;
53
54 va_start(args, fmt);
55 _eprintf(1, fmt, args);
56 va_end(args);
57 eprintf(1, "\n");
58}
59
36int dump_printf(const char *fmt, ...) 60int dump_printf(const char *fmt, ...)
37{ 61{
38 va_list args; 62 va_list args;
diff --git a/tools/perf/util/debug.h b/tools/perf/util/debug.h
index efbd98805ad0..443694c36b03 100644
--- a/tools/perf/util/debug.h
+++ b/tools/perf/util/debug.h
@@ -17,4 +17,6 @@ void trace_event(union perf_event *event);
17int ui__error(const char *format, ...) __attribute__((format(printf, 1, 2))); 17int ui__error(const char *format, ...) __attribute__((format(printf, 1, 2)));
18int ui__warning(const char *format, ...) __attribute__((format(printf, 1, 2))); 18int ui__warning(const char *format, ...) __attribute__((format(printf, 1, 2)));
19 19
20void pr_stat(const char *fmt, ...);
21
20#endif /* __PERF_DEBUG_H */ 22#endif /* __PERF_DEBUG_H */
diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c
index af4c687cc49b..a0c7c591f4b2 100644
--- a/tools/perf/util/dso.c
+++ b/tools/perf/util/dso.c
@@ -451,6 +451,7 @@ struct dso *dso__new(const char *name)
451 dso->sorted_by_name = 0; 451 dso->sorted_by_name = 0;
452 dso->has_build_id = 0; 452 dso->has_build_id = 0;
453 dso->has_srcline = 1; 453 dso->has_srcline = 1;
454 dso->a2l_fails = 1;
454 dso->kernel = DSO_TYPE_USER; 455 dso->kernel = DSO_TYPE_USER;
455 dso->needs_swap = DSO_SWAP__UNSET; 456 dso->needs_swap = DSO_SWAP__UNSET;
456 INIT_LIST_HEAD(&dso->node); 457 INIT_LIST_HEAD(&dso->node);
@@ -469,6 +470,8 @@ void dso__delete(struct dso *dso)
469 if (dso->lname_alloc) 470 if (dso->lname_alloc)
470 free(dso->long_name); 471 free(dso->long_name);
471 dso_cache__free(&dso->cache); 472 dso_cache__free(&dso->cache);
473 dso__free_a2l(dso);
474 free(dso->symsrc_filename);
472 free(dso); 475 free(dso);
473} 476}
474 477
diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h
index 9ac666abbe7e..384f2d97e38e 100644
--- a/tools/perf/util/dso.h
+++ b/tools/perf/util/dso.h
@@ -77,6 +77,9 @@ struct dso {
77 struct rb_root symbols[MAP__NR_TYPES]; 77 struct rb_root symbols[MAP__NR_TYPES];
78 struct rb_root symbol_names[MAP__NR_TYPES]; 78 struct rb_root symbol_names[MAP__NR_TYPES];
79 struct rb_root cache; 79 struct rb_root cache;
80 void *a2l;
81 char *symsrc_filename;
82 unsigned int a2l_fails;
80 enum dso_kernel_type kernel; 83 enum dso_kernel_type kernel;
81 enum dso_swap_type needs_swap; 84 enum dso_swap_type needs_swap;
82 enum dso_binary_type symtab_type; 85 enum dso_binary_type symtab_type;
@@ -166,4 +169,6 @@ static inline bool dso__is_kcore(struct dso *dso)
166 dso->data_type == DSO_BINARY_TYPE__GUEST_KCORE; 169 dso->data_type == DSO_BINARY_TYPE__GUEST_KCORE;
167} 170}
168 171
172void dso__free_a2l(struct dso *dso);
173
169#endif /* __PERF_DSO */ 174#endif /* __PERF_DSO */
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index 76fa76431329..7bb6ee1ca19f 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -819,13 +819,7 @@ int perf_evlist__create_maps(struct perf_evlist *evlist, struct target *target)
819 if (evlist->threads == NULL) 819 if (evlist->threads == NULL)
820 return -1; 820 return -1;
821 821
822 if (target->default_per_cpu) 822 if (target__uses_dummy_map(target))
823 evlist->cpus = target->per_thread ?
824 cpu_map__dummy_new() :
825 cpu_map__new(target->cpu_list);
826 else if (target__has_task(target))
827 evlist->cpus = cpu_map__dummy_new();
828 else if (!target__has_cpu(target) && !target->uses_mmap)
829 evlist->cpus = cpu_map__dummy_new(); 823 evlist->cpus = cpu_map__dummy_new();
830 else 824 else
831 evlist->cpus = cpu_map__new(target->cpu_list); 825 evlist->cpus = cpu_map__new(target->cpu_list);
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index b5fe7f9b2e15..7b510fd1f08d 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -23,6 +23,7 @@
23#include "target.h" 23#include "target.h"
24#include "perf_regs.h" 24#include "perf_regs.h"
25#include "debug.h" 25#include "debug.h"
26#include "trace-event.h"
26 27
27static struct { 28static struct {
28 bool sample_id_all; 29 bool sample_id_all;
@@ -180,47 +181,6 @@ struct perf_evsel *perf_evsel__new_idx(struct perf_event_attr *attr, int idx)
180 return evsel; 181 return evsel;
181} 182}
182 183
183struct event_format *event_format__new(const char *sys, const char *name)
184{
185 int fd, n;
186 char *filename;
187 void *bf = NULL, *nbf;
188 size_t size = 0, alloc_size = 0;
189 struct event_format *format = NULL;
190
191 if (asprintf(&filename, "%s/%s/%s/format", tracing_events_path, sys, name) < 0)
192 goto out;
193
194 fd = open(filename, O_RDONLY);
195 if (fd < 0)
196 goto out_free_filename;
197
198 do {
199 if (size == alloc_size) {
200 alloc_size += BUFSIZ;
201 nbf = realloc(bf, alloc_size);
202 if (nbf == NULL)
203 goto out_free_bf;
204 bf = nbf;
205 }
206
207 n = read(fd, bf + size, alloc_size - size);
208 if (n < 0)
209 goto out_free_bf;
210 size += n;
211 } while (n > 0);
212
213 pevent_parse_format(&format, bf, size, sys);
214
215out_free_bf:
216 free(bf);
217 close(fd);
218out_free_filename:
219 free(filename);
220out:
221 return format;
222}
223
224struct perf_evsel *perf_evsel__newtp_idx(const char *sys, const char *name, int idx) 184struct perf_evsel *perf_evsel__newtp_idx(const char *sys, const char *name, int idx)
225{ 185{
226 struct perf_evsel *evsel = zalloc(sizeof(*evsel)); 186 struct perf_evsel *evsel = zalloc(sizeof(*evsel));
@@ -235,7 +195,7 @@ struct perf_evsel *perf_evsel__newtp_idx(const char *sys, const char *name, int
235 if (asprintf(&evsel->name, "%s:%s", sys, name) < 0) 195 if (asprintf(&evsel->name, "%s:%s", sys, name) < 0)
236 goto out_free; 196 goto out_free;
237 197
238 evsel->tp_format = event_format__new(sys, name); 198 evsel->tp_format = trace_event__tp_format(sys, name);
239 if (evsel->tp_format == NULL) 199 if (evsel->tp_format == NULL)
240 goto out_free; 200 goto out_free;
241 201
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 3e755f2bfe8f..125cdc9250ee 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -2834,11 +2834,11 @@ int perf_session__read_header(struct perf_session *session)
2834 2834
2835 symbol_conf.nr_events = nr_attrs; 2835 symbol_conf.nr_events = nr_attrs;
2836 2836
2837 perf_header__process_sections(header, fd, &session->pevent, 2837 perf_header__process_sections(header, fd, &session->tevent,
2838 perf_file_section__process); 2838 perf_file_section__process);
2839 2839
2840 if (perf_evlist__prepare_tracepoint_events(session->evlist, 2840 if (perf_evlist__prepare_tracepoint_events(session->evlist,
2841 session->pevent)) 2841 session->tevent.pevent))
2842 goto out_delete_evlist; 2842 goto out_delete_evlist;
2843 2843
2844 return 0; 2844 return 0;
@@ -3003,7 +3003,7 @@ int perf_event__process_tracing_data(struct perf_tool *tool __maybe_unused,
3003 lseek(fd, offset + sizeof(struct tracing_data_event), 3003 lseek(fd, offset + sizeof(struct tracing_data_event),
3004 SEEK_SET); 3004 SEEK_SET);
3005 3005
3006 size_read = trace_report(fd, &session->pevent, 3006 size_read = trace_report(fd, &session->tevent,
3007 session->repipe); 3007 session->repipe);
3008 padding = PERF_ALIGN(size_read, sizeof(u64)) - size_read; 3008 padding = PERF_ALIGN(size_read, sizeof(u64)) - size_read;
3009 3009
@@ -3025,7 +3025,7 @@ int perf_event__process_tracing_data(struct perf_tool *tool __maybe_unused,
3025 } 3025 }
3026 3026
3027 perf_evlist__prepare_tracepoint_events(session->evlist, 3027 perf_evlist__prepare_tracepoint_events(session->evlist,
3028 session->pevent); 3028 session->tevent.pevent);
3029 3029
3030 return size_read + padding; 3030 return size_read + padding;
3031} 3031}
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
index 84cdb072ac83..bac817ab2068 100644
--- a/tools/perf/util/machine.c
+++ b/tools/perf/util/machine.c
@@ -502,15 +502,11 @@ static u64 machine__get_kernel_start_addr(struct machine *machine)
502 char path[PATH_MAX]; 502 char path[PATH_MAX];
503 struct process_args args; 503 struct process_args args;
504 504
505 if (machine__is_host(machine)) { 505 if (machine__is_default_guest(machine))
506 filename = "/proc/kallsyms"; 506 filename = (char *)symbol_conf.default_guest_kallsyms;
507 } else { 507 else {
508 if (machine__is_default_guest(machine)) 508 sprintf(path, "%s/proc/kallsyms", machine->root_dir);
509 filename = (char *)symbol_conf.default_guest_kallsyms; 509 filename = path;
510 else {
511 sprintf(path, "%s/proc/kallsyms", machine->root_dir);
512 filename = path;
513 }
514 } 510 }
515 511
516 if (symbol__restricted_filename(filename, "/proc/kallsyms")) 512 if (symbol__restricted_filename(filename, "/proc/kallsyms"))
diff --git a/tools/perf/util/python-ext-sources b/tools/perf/util/python-ext-sources
index 239036fb2b2c..595bfc73d2ed 100644
--- a/tools/perf/util/python-ext-sources
+++ b/tools/perf/util/python-ext-sources
@@ -18,4 +18,5 @@ util/cgroup.c
18util/rblist.c 18util/rblist.c
19util/strlist.c 19util/strlist.c
20util/fs.c 20util/fs.c
21util/trace-event.c
21../../lib/rbtree.c 22../../lib/rbtree.c
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 4ce146bae552..8a7da6f4a569 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -1487,11 +1487,10 @@ struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session,
1487 return NULL; 1487 return NULL;
1488} 1488}
1489 1489
1490void perf_evsel__print_ip(struct perf_evsel *evsel, union perf_event *event, 1490void perf_evsel__print_ip(struct perf_evsel *evsel, struct perf_sample *sample,
1491 struct perf_sample *sample, struct machine *machine, 1491 struct machine *machine, struct addr_location *al,
1492 unsigned int print_opts, unsigned int stack_depth) 1492 unsigned int print_opts, unsigned int stack_depth)
1493{ 1493{
1494 struct addr_location al;
1495 struct callchain_cursor_node *node; 1494 struct callchain_cursor_node *node;
1496 int print_ip = print_opts & PRINT_IP_OPT_IP; 1495 int print_ip = print_opts & PRINT_IP_OPT_IP;
1497 int print_sym = print_opts & PRINT_IP_OPT_SYM; 1496 int print_sym = print_opts & PRINT_IP_OPT_SYM;
@@ -1500,15 +1499,10 @@ void perf_evsel__print_ip(struct perf_evsel *evsel, union perf_event *event,
1500 int print_oneline = print_opts & PRINT_IP_OPT_ONELINE; 1499 int print_oneline = print_opts & PRINT_IP_OPT_ONELINE;
1501 char s = print_oneline ? ' ' : '\t'; 1500 char s = print_oneline ? ' ' : '\t';
1502 1501
1503 if (perf_event__preprocess_sample(event, machine, &al, sample) < 0) {
1504 error("problem processing %d event, skipping it.\n",
1505 event->header.type);
1506 return;
1507 }
1508
1509 if (symbol_conf.use_callchain && sample->callchain) { 1502 if (symbol_conf.use_callchain && sample->callchain) {
1503 struct addr_location node_al;
1510 1504
1511 if (machine__resolve_callchain(machine, evsel, al.thread, 1505 if (machine__resolve_callchain(machine, evsel, al->thread,
1512 sample, NULL, NULL, 1506 sample, NULL, NULL,
1513 PERF_MAX_STACK_DEPTH) != 0) { 1507 PERF_MAX_STACK_DEPTH) != 0) {
1514 if (verbose) 1508 if (verbose)
@@ -1517,6 +1511,9 @@ void perf_evsel__print_ip(struct perf_evsel *evsel, union perf_event *event,
1517 } 1511 }
1518 callchain_cursor_commit(&callchain_cursor); 1512 callchain_cursor_commit(&callchain_cursor);
1519 1513
1514 if (print_symoffset)
1515 node_al = *al;
1516
1520 while (stack_depth) { 1517 while (stack_depth) {
1521 node = callchain_cursor_current(&callchain_cursor); 1518 node = callchain_cursor_current(&callchain_cursor);
1522 if (!node) 1519 if (!node)
@@ -1531,9 +1528,9 @@ void perf_evsel__print_ip(struct perf_evsel *evsel, union perf_event *event,
1531 if (print_sym) { 1528 if (print_sym) {
1532 printf(" "); 1529 printf(" ");
1533 if (print_symoffset) { 1530 if (print_symoffset) {
1534 al.addr = node->ip; 1531 node_al.addr = node->ip;
1535 al.map = node->map; 1532 node_al.map = node->map;
1536 symbol__fprintf_symname_offs(node->sym, &al, stdout); 1533 symbol__fprintf_symname_offs(node->sym, &node_al, stdout);
1537 } else 1534 } else
1538 symbol__fprintf_symname(node->sym, stdout); 1535 symbol__fprintf_symname(node->sym, stdout);
1539 } 1536 }
@@ -1553,7 +1550,7 @@ next:
1553 } 1550 }
1554 1551
1555 } else { 1552 } else {
1556 if (al.sym && al.sym->ignore) 1553 if (al->sym && al->sym->ignore)
1557 return; 1554 return;
1558 1555
1559 if (print_ip) 1556 if (print_ip)
@@ -1562,15 +1559,15 @@ next:
1562 if (print_sym) { 1559 if (print_sym) {
1563 printf(" "); 1560 printf(" ");
1564 if (print_symoffset) 1561 if (print_symoffset)
1565 symbol__fprintf_symname_offs(al.sym, &al, 1562 symbol__fprintf_symname_offs(al->sym, al,
1566 stdout); 1563 stdout);
1567 else 1564 else
1568 symbol__fprintf_symname(al.sym, stdout); 1565 symbol__fprintf_symname(al->sym, stdout);
1569 } 1566 }
1570 1567
1571 if (print_dso) { 1568 if (print_dso) {
1572 printf(" ("); 1569 printf(" (");
1573 map__fprintf_dsoname(al.map, stdout); 1570 map__fprintf_dsoname(al->map, stdout);
1574 printf(")"); 1571 printf(")");
1575 } 1572 }
1576 } 1573 }
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h
index 50f640958f0f..004d3e8116aa 100644
--- a/tools/perf/util/session.h
+++ b/tools/perf/util/session.h
@@ -1,6 +1,7 @@
1#ifndef __PERF_SESSION_H 1#ifndef __PERF_SESSION_H
2#define __PERF_SESSION_H 2#define __PERF_SESSION_H
3 3
4#include "trace-event.h"
4#include "hist.h" 5#include "hist.h"
5#include "event.h" 6#include "event.h"
6#include "header.h" 7#include "header.h"
@@ -32,7 +33,7 @@ struct perf_session {
32 struct perf_header header; 33 struct perf_header header;
33 struct machines machines; 34 struct machines machines;
34 struct perf_evlist *evlist; 35 struct perf_evlist *evlist;
35 struct pevent *pevent; 36 struct trace_event tevent;
36 struct events_stats stats; 37 struct events_stats stats;
37 bool repipe; 38 bool repipe;
38 struct ordered_samples ordered_samples; 39 struct ordered_samples ordered_samples;
@@ -105,8 +106,8 @@ size_t perf_session__fprintf_nr_events(struct perf_session *session, FILE *fp);
105struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session, 106struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session,
106 unsigned int type); 107 unsigned int type);
107 108
108void perf_evsel__print_ip(struct perf_evsel *evsel, union perf_event *event, 109void perf_evsel__print_ip(struct perf_evsel *evsel, struct perf_sample *sample,
109 struct perf_sample *sample, struct machine *machine, 110 struct machine *machine, struct addr_location *al,
110 unsigned int print_opts, unsigned int stack_depth); 111 unsigned int print_opts, unsigned int stack_depth);
111 112
112int perf_session__cpu_bitmap(struct perf_session *session, 113int perf_session__cpu_bitmap(struct perf_session *session,
diff --git a/tools/perf/util/srcline.c b/tools/perf/util/srcline.c
index d11aefbc4b8d..0c075560ad46 100644
--- a/tools/perf/util/srcline.c
+++ b/tools/perf/util/srcline.c
@@ -146,18 +146,24 @@ static void addr2line_cleanup(struct a2l_data *a2l)
146} 146}
147 147
148static int addr2line(const char *dso_name, unsigned long addr, 148static int addr2line(const char *dso_name, unsigned long addr,
149 char **file, unsigned int *line) 149 char **file, unsigned int *line, struct dso *dso)
150{ 150{
151 int ret = 0; 151 int ret = 0;
152 struct a2l_data *a2l; 152 struct a2l_data *a2l = dso->a2l;
153
154 if (!a2l) {
155 dso->a2l = addr2line_init(dso_name);
156 a2l = dso->a2l;
157 }
153 158
154 a2l = addr2line_init(dso_name);
155 if (a2l == NULL) { 159 if (a2l == NULL) {
156 pr_warning("addr2line_init failed for %s\n", dso_name); 160 pr_warning("addr2line_init failed for %s\n", dso_name);
157 return 0; 161 return 0;
158 } 162 }
159 163
160 a2l->addr = addr; 164 a2l->addr = addr;
165 a2l->found = false;
166
161 bfd_map_over_sections(a2l->abfd, find_address_in_section, a2l); 167 bfd_map_over_sections(a2l->abfd, find_address_in_section, a2l);
162 168
163 if (a2l->found && a2l->filename) { 169 if (a2l->found && a2l->filename) {
@@ -168,14 +174,26 @@ static int addr2line(const char *dso_name, unsigned long addr,
168 ret = 1; 174 ret = 1;
169 } 175 }
170 176
171 addr2line_cleanup(a2l);
172 return ret; 177 return ret;
173} 178}
174 179
180void dso__free_a2l(struct dso *dso)
181{
182 struct a2l_data *a2l = dso->a2l;
183
184 if (!a2l)
185 return;
186
187 addr2line_cleanup(a2l);
188
189 dso->a2l = NULL;
190}
191
175#else /* HAVE_LIBBFD_SUPPORT */ 192#else /* HAVE_LIBBFD_SUPPORT */
176 193
177static int addr2line(const char *dso_name, unsigned long addr, 194static int addr2line(const char *dso_name, unsigned long addr,
178 char **file, unsigned int *line_nr) 195 char **file, unsigned int *line_nr,
196 struct dso *dso __maybe_unused)
179{ 197{
180 FILE *fp; 198 FILE *fp;
181 char cmd[PATH_MAX]; 199 char cmd[PATH_MAX];
@@ -219,42 +237,58 @@ out:
219 pclose(fp); 237 pclose(fp);
220 return ret; 238 return ret;
221} 239}
240
241void dso__free_a2l(struct dso *dso __maybe_unused)
242{
243}
244
222#endif /* HAVE_LIBBFD_SUPPORT */ 245#endif /* HAVE_LIBBFD_SUPPORT */
223 246
247/*
248 * Number of addr2line failures (without success) before disabling it for that
249 * dso.
250 */
251#define A2L_FAIL_LIMIT 123
252
224char *get_srcline(struct dso *dso, unsigned long addr) 253char *get_srcline(struct dso *dso, unsigned long addr)
225{ 254{
226 char *file = NULL; 255 char *file = NULL;
227 unsigned line = 0; 256 unsigned line = 0;
228 char *srcline; 257 char *srcline;
229 char *dso_name = dso->long_name; 258 char *dso_name;
230 size_t size;
231 259
232 if (!dso->has_srcline) 260 if (!dso->has_srcline)
233 return SRCLINE_UNKNOWN; 261 return SRCLINE_UNKNOWN;
234 262
263 if (dso->symsrc_filename)
264 dso_name = dso->symsrc_filename;
265 else
266 dso_name = dso->long_name;
267
235 if (dso_name[0] == '[') 268 if (dso_name[0] == '[')
236 goto out; 269 goto out;
237 270
238 if (!strncmp(dso_name, "/tmp/perf-", 10)) 271 if (!strncmp(dso_name, "/tmp/perf-", 10))
239 goto out; 272 goto out;
240 273
241 if (!addr2line(dso_name, addr, &file, &line)) 274 if (!addr2line(dso_name, addr, &file, &line, dso))
242 goto out; 275 goto out;
243 276
244 /* just calculate actual length */ 277 if (asprintf(&srcline, "%s:%u", file, line) < 0) {
245 size = snprintf(NULL, 0, "%s:%u", file, line) + 1; 278 free(file);
279 goto out;
280 }
246 281
247 srcline = malloc(size); 282 dso->a2l_fails = 0;
248 if (srcline)
249 snprintf(srcline, size, "%s:%u", file, line);
250 else
251 srcline = SRCLINE_UNKNOWN;
252 283
253 free(file); 284 free(file);
254 return srcline; 285 return srcline;
255 286
256out: 287out:
257 dso->has_srcline = 0; 288 if (dso->a2l_fails && ++dso->a2l_fails > A2L_FAIL_LIMIT) {
289 dso->has_srcline = 0;
290 dso__free_a2l(dso);
291 }
258 return SRCLINE_UNKNOWN; 292 return SRCLINE_UNKNOWN;
259} 293}
260 294
diff --git a/tools/perf/util/symbol-minimal.c b/tools/perf/util/symbol-minimal.c
index 2d2dd0532b5a..ac7070a2f2b6 100644
--- a/tools/perf/util/symbol-minimal.c
+++ b/tools/perf/util/symbol-minimal.c
@@ -253,6 +253,7 @@ int symsrc__init(struct symsrc *ss, struct dso *dso __maybe_unused,
253 if (!ss->name) 253 if (!ss->name)
254 goto out_close; 254 goto out_close;
255 255
256 ss->fd = fd;
256 ss->type = type; 257 ss->type = type;
257 258
258 return 0; 259 return 0;
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index 360eefecb81d..de87dbac50a0 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -1336,6 +1336,8 @@ int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter)
1336 if (!syms_ss && symsrc__has_symtab(ss)) { 1336 if (!syms_ss && symsrc__has_symtab(ss)) {
1337 syms_ss = ss; 1337 syms_ss = ss;
1338 next_slot = true; 1338 next_slot = true;
1339 if (!dso->symsrc_filename)
1340 dso->symsrc_filename = strdup(name);
1339 } 1341 }
1340 1342
1341 if (!runtime_ss && symsrc__possibly_runtime(ss)) { 1343 if (!runtime_ss && symsrc__possibly_runtime(ss)) {
diff --git a/tools/perf/util/target.h b/tools/perf/util/target.h
index 31dd2e9a27d0..7381b1ca4041 100644
--- a/tools/perf/util/target.h
+++ b/tools/perf/util/target.h
@@ -63,4 +63,17 @@ static inline bool target__none(struct target *target)
63 return !target__has_task(target) && !target__has_cpu(target); 63 return !target__has_task(target) && !target__has_cpu(target);
64} 64}
65 65
66static inline bool target__uses_dummy_map(struct target *target)
67{
68 bool use_dummy = false;
69
70 if (target->default_per_cpu)
71 use_dummy = target->per_thread ? true : false;
72 else if (target__has_task(target) ||
73 (!target__has_cpu(target) && !target->uses_mmap))
74 use_dummy = true;
75
76 return use_dummy;
77}
78
66#endif /* _PERF_TARGET_H */ 79#endif /* _PERF_TARGET_H */
diff --git a/tools/perf/util/trace-event-parse.c b/tools/perf/util/trace-event-parse.c
index 6681f71f2f95..e0d6d07f6848 100644
--- a/tools/perf/util/trace-event-parse.c
+++ b/tools/perf/util/trace-event-parse.c
@@ -28,19 +28,6 @@
28#include "util.h" 28#include "util.h"
29#include "trace-event.h" 29#include "trace-event.h"
30 30
31struct pevent *read_trace_init(int file_bigendian, int host_bigendian)
32{
33 struct pevent *pevent = pevent_alloc();
34
35 if (pevent != NULL) {
36 pevent_set_flag(pevent, PEVENT_NSEC_OUTPUT);
37 pevent_set_file_bigendian(pevent, file_bigendian);
38 pevent_set_host_bigendian(pevent, host_bigendian);
39 }
40
41 return pevent;
42}
43
44static int get_common_field(struct scripting_context *context, 31static int get_common_field(struct scripting_context *context,
45 int *offset, int *size, const char *type) 32 int *offset, int *size, const char *type)
46{ 33{
diff --git a/tools/perf/util/trace-event-read.c b/tools/perf/util/trace-event-read.c
index f2112270c663..e113e180c48f 100644
--- a/tools/perf/util/trace-event-read.c
+++ b/tools/perf/util/trace-event-read.c
@@ -343,7 +343,7 @@ static int read_event_files(struct pevent *pevent)
343 return 0; 343 return 0;
344} 344}
345 345
346ssize_t trace_report(int fd, struct pevent **ppevent, bool __repipe) 346ssize_t trace_report(int fd, struct trace_event *tevent, bool __repipe)
347{ 347{
348 char buf[BUFSIZ]; 348 char buf[BUFSIZ];
349 char test[] = { 23, 8, 68 }; 349 char test[] = { 23, 8, 68 };
@@ -356,11 +356,9 @@ ssize_t trace_report(int fd, struct pevent **ppevent, bool __repipe)
356 int host_bigendian; 356 int host_bigendian;
357 int file_long_size; 357 int file_long_size;
358 int file_page_size; 358 int file_page_size;
359 struct pevent *pevent; 359 struct pevent *pevent = NULL;
360 int err; 360 int err;
361 361
362 *ppevent = NULL;
363
364 repipe = __repipe; 362 repipe = __repipe;
365 input_fd = fd; 363 input_fd = fd;
366 364
@@ -390,12 +388,17 @@ ssize_t trace_report(int fd, struct pevent **ppevent, bool __repipe)
390 file_bigendian = buf[0]; 388 file_bigendian = buf[0];
391 host_bigendian = bigendian(); 389 host_bigendian = bigendian();
392 390
393 pevent = read_trace_init(file_bigendian, host_bigendian); 391 if (trace_event__init(tevent)) {
394 if (pevent == NULL) { 392 pr_debug("trace_event__init failed");
395 pr_debug("read_trace_init failed");
396 goto out; 393 goto out;
397 } 394 }
398 395
396 pevent = tevent->pevent;
397
398 pevent_set_flag(pevent, PEVENT_NSEC_OUTPUT);
399 pevent_set_file_bigendian(pevent, file_bigendian);
400 pevent_set_host_bigendian(pevent, host_bigendian);
401
399 if (do_read(buf, 1) < 0) 402 if (do_read(buf, 1) < 0)
400 goto out; 403 goto out;
401 file_long_size = buf[0]; 404 file_long_size = buf[0];
@@ -432,11 +435,10 @@ ssize_t trace_report(int fd, struct pevent **ppevent, bool __repipe)
432 pevent_print_printk(pevent); 435 pevent_print_printk(pevent);
433 } 436 }
434 437
435 *ppevent = pevent;
436 pevent = NULL; 438 pevent = NULL;
437 439
438out: 440out:
439 if (pevent) 441 if (pevent)
440 pevent_free(pevent); 442 trace_event__cleanup(tevent);
441 return size; 443 return size;
442} 444}
diff --git a/tools/perf/util/trace-event.c b/tools/perf/util/trace-event.c
new file mode 100644
index 000000000000..d9f5f6137ab3
--- /dev/null
+++ b/tools/perf/util/trace-event.c
@@ -0,0 +1,82 @@
1
2#include <stdio.h>
3#include <unistd.h>
4#include <stdlib.h>
5#include <errno.h>
6#include <sys/types.h>
7#include <sys/stat.h>
8#include <fcntl.h>
9#include <linux/kernel.h>
10#include <traceevent/event-parse.h>
11#include "trace-event.h"
12#include "util.h"
13
14/*
15 * global trace_event object used by trace_event__tp_format
16 *
17 * TODO There's no cleanup call for this. Add some sort of
18 * __exit function support and call trace_event__cleanup
19 * there.
20 */
21static struct trace_event tevent;
22
23int trace_event__init(struct trace_event *t)
24{
25 struct pevent *pevent = pevent_alloc();
26
27 if (pevent) {
28 t->plugin_list = traceevent_load_plugins(pevent);
29 t->pevent = pevent;
30 }
31
32 return pevent ? 0 : -1;
33}
34
35void trace_event__cleanup(struct trace_event *t)
36{
37 pevent_free(t->pevent);
38 traceevent_unload_plugins(t->plugin_list);
39}
40
41static struct event_format*
42tp_format(const char *sys, const char *name)
43{
44 struct pevent *pevent = tevent.pevent;
45 struct event_format *event = NULL;
46 char path[PATH_MAX];
47 size_t size;
48 char *data;
49
50 scnprintf(path, PATH_MAX, "%s/%s/%s/format",
51 tracing_events_path, sys, name);
52
53 if (filename__read_str(path, &data, &size))
54 return NULL;
55
56 pevent_parse_format(pevent, &event, data, size, sys);
57
58 free(data);
59 return event;
60}
61
62struct event_format*
63trace_event__tp_format(const char *sys, const char *name)
64{
65 static bool initialized;
66
67 if (!initialized) {
68 int be = traceevent_host_bigendian();
69 struct pevent *pevent;
70
71 if (trace_event__init(&tevent))
72 return NULL;
73
74 pevent = tevent.pevent;
75 pevent_set_flag(pevent, PEVENT_NSEC_OUTPUT);
76 pevent_set_file_bigendian(pevent, be);
77 pevent_set_host_bigendian(pevent, be);
78 initialized = true;
79 }
80
81 return tp_format(sys, name);
82}
diff --git a/tools/perf/util/trace-event.h b/tools/perf/util/trace-event.h
index 04df63114109..3a01618c5b87 100644
--- a/tools/perf/util/trace-event.h
+++ b/tools/perf/util/trace-event.h
@@ -3,17 +3,26 @@
3 3
4#include <traceevent/event-parse.h> 4#include <traceevent/event-parse.h>
5#include "parse-events.h" 5#include "parse-events.h"
6#include "session.h"
7 6
8struct machine; 7struct machine;
9struct perf_sample; 8struct perf_sample;
10union perf_event; 9union perf_event;
11struct perf_tool; 10struct perf_tool;
12struct thread; 11struct thread;
12struct plugin_list;
13
14struct trace_event {
15 struct pevent *pevent;
16 struct plugin_list *plugin_list;
17};
18
19int trace_event__init(struct trace_event *t);
20void trace_event__cleanup(struct trace_event *t);
21struct event_format*
22trace_event__tp_format(const char *sys, const char *name);
13 23
14int bigendian(void); 24int bigendian(void);
15 25
16struct pevent *read_trace_init(int file_bigendian, int host_bigendian);
17void event_format__print(struct event_format *event, 26void event_format__print(struct event_format *event,
18 int cpu, void *data, int size); 27 int cpu, void *data, int size);
19 28
@@ -27,7 +36,7 @@ raw_field_value(struct event_format *event, const char *name, void *data);
27void parse_proc_kallsyms(struct pevent *pevent, char *file, unsigned int size); 36void parse_proc_kallsyms(struct pevent *pevent, char *file, unsigned int size);
28void parse_ftrace_printk(struct pevent *pevent, char *file, unsigned int size); 37void parse_ftrace_printk(struct pevent *pevent, char *file, unsigned int size);
29 38
30ssize_t trace_report(int fd, struct pevent **pevent, bool repipe); 39ssize_t trace_report(int fd, struct trace_event *tevent, bool repipe);
31 40
32struct event_format *trace_find_next_event(struct pevent *pevent, 41struct event_format *trace_find_next_event(struct pevent *pevent,
33 struct event_format *event); 42 struct event_format *event);
diff --git a/tools/perf/util/util.c b/tools/perf/util/util.c
index b1d5376b9dd9..bae8756a4eb1 100644
--- a/tools/perf/util/util.c
+++ b/tools/perf/util/util.c
@@ -6,6 +6,8 @@
6#endif 6#endif
7#include <stdio.h> 7#include <stdio.h>
8#include <stdlib.h> 8#include <stdlib.h>
9#include <string.h>
10#include <errno.h>
9#include <linux/kernel.h> 11#include <linux/kernel.h>
10 12
11/* 13/*
@@ -433,3 +435,50 @@ int filename__read_int(const char *filename, int *value)
433 close(fd); 435 close(fd);
434 return err; 436 return err;
435} 437}
438
439int filename__read_str(const char *filename, char **buf, size_t *sizep)
440{
441 size_t size = 0, alloc_size = 0;
442 void *bf = NULL, *nbf;
443 int fd, n, err = 0;
444
445 fd = open(filename, O_RDONLY);
446 if (fd < 0)
447 return -errno;
448
449 do {
450 if (size == alloc_size) {
451 alloc_size += BUFSIZ;
452 nbf = realloc(bf, alloc_size);
453 if (!nbf) {
454 err = -ENOMEM;
455 break;
456 }
457
458 bf = nbf;
459 }
460
461 n = read(fd, bf + size, alloc_size - size);
462 if (n < 0) {
463 if (size) {
464 pr_warning("read failed %d: %s\n",
465 errno, strerror(errno));
466 err = 0;
467 } else
468 err = -errno;
469
470 break;
471 }
472
473 size += n;
474 } while (n > 0);
475
476 if (!err) {
477 *sizep = size;
478 *buf = bf;
479 } else
480 free(bf);
481
482 close(fd);
483 return err;
484}
diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h
index ce0f73d4d91f..adb39f251f90 100644
--- a/tools/perf/util/util.h
+++ b/tools/perf/util/util.h
@@ -308,4 +308,5 @@ char *get_srcline(struct dso *dso, unsigned long addr);
308void free_srcline(char *srcline); 308void free_srcline(char *srcline);
309 309
310int filename__read_int(const char *filename, int *value); 310int filename__read_int(const char *filename, int *value);
311int filename__read_str(const char *filename, char **buf, size_t *sizep);
311#endif /* GIT_COMPAT_UTIL_H */ 312#endif /* GIT_COMPAT_UTIL_H */