aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIngo Molnar <mingo@kernel.org>2013-12-18 05:10:03 -0500
committerIngo Molnar <mingo@kernel.org>2013-12-18 08:07:26 -0500
commitfa6e8e5f7cbf85f364ebd5a90525dbbe9de2083b (patch)
treea85962bf1567292ac58f8340edc16f6cc35ea918
parent9450d14fb959336803e5209119eb422b667b96aa (diff)
parentf23b24f1bf90b56cfaeb2a1c9b77c46efe8916a6 (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 refactorings from Arnaldo Carvalho de Melo: New features: . In perf timechart: - Add backtrace support to CPU info . Print pid along the name . Add support for CPU topology . Add new option --highlight'ing threads, be it by name or, if a numeric value is provided, that run more than given duration. From Stanislav Fomichev. Refactorings: . Rename some struct DSO binary_type related members and methods, to clarify its purpose and need for differentiation from symtab_type, i.e. one is about the files .text, CFI, etc, i.e. its binary contents, and the other is about where the symbol table came from. . Convert to new topic libraries, starting with an API one (sysfs, debugfs, etc), renaming liblk in the process, from Borislav Petkov. . Get rid of some more panic() like error handling in libtraceevent, from Namhyung Kim. Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> Signed-off-by: Ingo Molnar <mingo@kernel.org>
-rw-r--r--tools/Makefile12
-rw-r--r--tools/lib/api/Makefile (renamed from tools/lib/lk/Makefile)18
-rw-r--r--tools/lib/api/fs/debugfs.c (renamed from tools/lib/lk/debugfs.c)0
-rw-r--r--tools/lib/api/fs/debugfs.h (renamed from tools/lib/lk/debugfs.h)6
-rw-r--r--tools/lib/traceevent/parse-filter.c67
-rw-r--r--tools/perf/Documentation/perf-timechart.txt16
-rw-r--r--tools/perf/Makefile.perf33
-rw-r--r--tools/perf/builtin-kvm.c2
-rw-r--r--tools/perf/builtin-probe.c2
-rw-r--r--tools/perf/builtin-timechart.c79
-rw-r--r--tools/perf/perf.c2
-rw-r--r--tools/perf/tests/parse-events.c2
-rw-r--r--tools/perf/util/dso.c24
-rw-r--r--tools/perf/util/dso.h14
-rw-r--r--tools/perf/util/evlist.c2
-rw-r--r--tools/perf/util/evsel.c2
-rw-r--r--tools/perf/util/parse-events.c2
-rw-r--r--tools/perf/util/probe-event.c2
-rw-r--r--tools/perf/util/setup.py4
-rw-r--r--tools/perf/util/svghelper.c159
-rw-r--r--tools/perf/util/svghelper.h6
-rw-r--r--tools/perf/util/symbol.c12
-rw-r--r--tools/perf/util/trace-event-info.c2
-rw-r--r--tools/perf/util/util.h2
-rw-r--r--tools/vm/Makefile14
-rw-r--r--tools/vm/page-types.c2
26 files changed, 344 insertions, 142 deletions
diff --git a/tools/Makefile b/tools/Makefile
index a9b02008443c..927cd46d36dc 100644
--- a/tools/Makefile
+++ b/tools/Makefile
@@ -39,10 +39,10 @@ cpupower: FORCE
39cgroup firewire guest usb virtio vm net: FORCE 39cgroup firewire guest usb virtio vm net: FORCE
40 $(call descend,$@) 40 $(call descend,$@)
41 41
42liblk: FORCE 42libapikfs: FORCE
43 $(call descend,lib/lk) 43 $(call descend,lib/api)
44 44
45perf: liblk FORCE 45perf: libapikfs FORCE
46 $(call descend,$@) 46 $(call descend,$@)
47 47
48selftests: FORCE 48selftests: FORCE
@@ -80,10 +80,10 @@ cpupower_clean:
80cgroup_clean firewire_clean lguest_clean usb_clean virtio_clean vm_clean net_clean: 80cgroup_clean firewire_clean lguest_clean usb_clean virtio_clean vm_clean net_clean:
81 $(call descend,$(@:_clean=),clean) 81 $(call descend,$(@:_clean=),clean)
82 82
83liblk_clean: 83libapikfs_clean:
84 $(call descend,lib/lk,clean) 84 $(call descend,lib/api,clean)
85 85
86perf_clean: liblk_clean 86perf_clean: libapikfs_clean
87 $(call descend,$(@:_clean=),clean) 87 $(call descend,$(@:_clean=),clean)
88 88
89selftests_clean: 89selftests_clean:
diff --git a/tools/lib/lk/Makefile b/tools/lib/api/Makefile
index 3dba0a4aebbf..ed2f51e11b80 100644
--- a/tools/lib/lk/Makefile
+++ b/tools/lib/api/Makefile
@@ -1,4 +1,5 @@
1include ../../scripts/Makefile.include 1include ../../scripts/Makefile.include
2include ../../perf/config/utilities.mak # QUIET_CLEAN
2 3
3CC = $(CROSS_COMPILE)gcc 4CC = $(CROSS_COMPILE)gcc
4AR = $(CROSS_COMPILE)ar 5AR = $(CROSS_COMPILE)ar
@@ -7,11 +8,11 @@ AR = $(CROSS_COMPILE)ar
7LIB_H= 8LIB_H=
8LIB_OBJS= 9LIB_OBJS=
9 10
10LIB_H += debugfs.h 11LIB_H += fs/debugfs.h
11 12
12LIB_OBJS += $(OUTPUT)debugfs.o 13LIB_OBJS += $(OUTPUT)fs/debugfs.o
13 14
14LIBFILE = liblk.a 15LIBFILE = libapikfs.a
15 16
16CFLAGS = -ggdb3 -Wall -Wextra -std=gnu99 -Werror -O6 -D_FORTIFY_SOURCE=2 $(EXTRA_WARNINGS) $(EXTRA_CFLAGS) -fPIC 17CFLAGS = -ggdb3 -Wall -Wextra -std=gnu99 -Werror -O6 -D_FORTIFY_SOURCE=2 $(EXTRA_WARNINGS) $(EXTRA_CFLAGS) -fPIC
17EXTLIBS = -lelf -lpthread -lrt -lm 18EXTLIBS = -lelf -lpthread -lrt -lm
@@ -25,14 +26,17 @@ $(LIBFILE): $(LIB_OBJS)
25 26
26$(LIB_OBJS): $(LIB_H) 27$(LIB_OBJS): $(LIB_H)
27 28
28$(OUTPUT)%.o: %.c 29libapi_dirs:
30 $(QUIET_MKDIR)mkdir -p $(OUTPUT)fs/
31
32$(OUTPUT)%.o: %.c libapi_dirs
29 $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) $< 33 $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) $<
30$(OUTPUT)%.s: %.c 34$(OUTPUT)%.s: %.c libapi_dirs
31 $(QUIET_CC)$(CC) -S $(ALL_CFLAGS) $< 35 $(QUIET_CC)$(CC) -S $(ALL_CFLAGS) $<
32$(OUTPUT)%.o: %.S 36$(OUTPUT)%.o: %.S libapi_dirs
33 $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) $< 37 $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) $<
34 38
35clean: 39clean:
36 $(RM) $(LIB_OBJS) $(LIBFILE) 40 $(call QUIET_CLEAN, libapi) $(RM) $(LIB_OBJS) $(LIBFILE)
37 41
38.PHONY: clean 42.PHONY: clean
diff --git a/tools/lib/lk/debugfs.c b/tools/lib/api/fs/debugfs.c
index 7c4347962353..7c4347962353 100644
--- a/tools/lib/lk/debugfs.c
+++ b/tools/lib/api/fs/debugfs.c
diff --git a/tools/lib/lk/debugfs.h b/tools/lib/api/fs/debugfs.h
index 935c59bdb442..f19d3df9609d 100644
--- a/tools/lib/lk/debugfs.h
+++ b/tools/lib/api/fs/debugfs.h
@@ -1,5 +1,5 @@
1#ifndef __LK_DEBUGFS_H__ 1#ifndef __API_DEBUGFS_H__
2#define __LK_DEBUGFS_H__ 2#define __API_DEBUGFS_H__
3 3
4#define _STR(x) #x 4#define _STR(x) #x
5#define STR(x) _STR(x) 5#define STR(x) _STR(x)
@@ -26,4 +26,4 @@ char *debugfs_mount(const char *mountpoint);
26 26
27extern char debugfs_mountpoint[]; 27extern char debugfs_mountpoint[];
28 28
29#endif /* __LK_DEBUGFS_H__ */ 29#endif /* __API_DEBUGFS_H__ */
diff --git a/tools/lib/traceevent/parse-filter.c b/tools/lib/traceevent/parse-filter.c
index 9303c55128db..e2842b926759 100644
--- a/tools/lib/traceevent/parse-filter.c
+++ b/tools/lib/traceevent/parse-filter.c
@@ -1361,8 +1361,10 @@ enum pevent_errno pevent_filter_add_filter_str(struct event_filter *filter,
1361 if (ret >= 0 && pevent->test_filters) { 1361 if (ret >= 0 && pevent->test_filters) {
1362 char *test; 1362 char *test;
1363 test = pevent_filter_make_string(filter, event->event->id); 1363 test = pevent_filter_make_string(filter, event->event->id);
1364 printf(" '%s: %s'\n", event->event->name, test); 1364 if (test) {
1365 free(test); 1365 printf(" '%s: %s'\n", event->event->name, test);
1366 free(test);
1367 }
1366 } 1368 }
1367 } 1369 }
1368 1370
@@ -2050,7 +2052,6 @@ static char *op_to_str(struct event_filter *filter, struct filter_arg *arg)
2050 int left_val = -1; 2052 int left_val = -1;
2051 int right_val = -1; 2053 int right_val = -1;
2052 int val; 2054 int val;
2053 int len;
2054 2055
2055 switch (arg->op.type) { 2056 switch (arg->op.type) {
2056 case FILTER_OP_AND: 2057 case FILTER_OP_AND:
@@ -2097,11 +2098,7 @@ static char *op_to_str(struct event_filter *filter, struct filter_arg *arg)
2097 default: 2098 default:
2098 break; 2099 break;
2099 } 2100 }
2100 str = malloc_or_die(6); 2101 asprintf(&str, val ? "TRUE" : "FALSE");
2101 if (val)
2102 strcpy(str, "TRUE");
2103 else
2104 strcpy(str, "FALSE");
2105 break; 2102 break;
2106 } 2103 }
2107 } 2104 }
@@ -2119,10 +2116,7 @@ static char *op_to_str(struct event_filter *filter, struct filter_arg *arg)
2119 break; 2116 break;
2120 } 2117 }
2121 2118
2122 len = strlen(left) + strlen(right) + strlen(op) + 10; 2119 asprintf(&str, "(%s) %s (%s)", left, op, right);
2123 str = malloc_or_die(len);
2124 snprintf(str, len, "(%s) %s (%s)",
2125 left, op, right);
2126 break; 2120 break;
2127 2121
2128 case FILTER_OP_NOT: 2122 case FILTER_OP_NOT:
@@ -2138,16 +2132,10 @@ static char *op_to_str(struct event_filter *filter, struct filter_arg *arg)
2138 right_val = 0; 2132 right_val = 0;
2139 if (right_val >= 0) { 2133 if (right_val >= 0) {
2140 /* just return the opposite */ 2134 /* just return the opposite */
2141 str = malloc_or_die(6); 2135 asprintf(&str, right_val ? "FALSE" : "TRUE");
2142 if (right_val)
2143 strcpy(str, "FALSE");
2144 else
2145 strcpy(str, "TRUE");
2146 break; 2136 break;
2147 } 2137 }
2148 len = strlen(right) + strlen(op) + 3; 2138 asprintf(&str, "%s(%s)", op, right);
2149 str = malloc_or_die(len);
2150 snprintf(str, len, "%s(%s)", op, right);
2151 break; 2139 break;
2152 2140
2153 default: 2141 default:
@@ -2161,11 +2149,9 @@ static char *op_to_str(struct event_filter *filter, struct filter_arg *arg)
2161 2149
2162static char *val_to_str(struct event_filter *filter, struct filter_arg *arg) 2150static char *val_to_str(struct event_filter *filter, struct filter_arg *arg)
2163{ 2151{
2164 char *str; 2152 char *str = NULL;
2165
2166 str = malloc_or_die(30);
2167 2153
2168 snprintf(str, 30, "%lld", arg->value.val); 2154 asprintf(&str, "%lld", arg->value.val);
2169 2155
2170 return str; 2156 return str;
2171} 2157}
@@ -2181,7 +2167,6 @@ static char *exp_to_str(struct event_filter *filter, struct filter_arg *arg)
2181 char *rstr; 2167 char *rstr;
2182 char *op; 2168 char *op;
2183 char *str = NULL; 2169 char *str = NULL;
2184 int len;
2185 2170
2186 lstr = arg_to_str(filter, arg->exp.left); 2171 lstr = arg_to_str(filter, arg->exp.left);
2187 rstr = arg_to_str(filter, arg->exp.right); 2172 rstr = arg_to_str(filter, arg->exp.right);
@@ -2220,12 +2205,11 @@ static char *exp_to_str(struct event_filter *filter, struct filter_arg *arg)
2220 op = "^"; 2205 op = "^";
2221 break; 2206 break;
2222 default: 2207 default:
2223 die("oops in exp"); 2208 op = "[ERROR IN EXPRESSION TYPE]";
2209 break;
2224 } 2210 }
2225 2211
2226 len = strlen(op) + strlen(lstr) + strlen(rstr) + 4; 2212 asprintf(&str, "%s %s %s", lstr, op, rstr);
2227 str = malloc_or_die(len);
2228 snprintf(str, len, "%s %s %s", lstr, op, rstr);
2229out: 2213out:
2230 free(lstr); 2214 free(lstr);
2231 free(rstr); 2215 free(rstr);
@@ -2239,7 +2223,6 @@ static char *num_to_str(struct event_filter *filter, struct filter_arg *arg)
2239 char *rstr; 2223 char *rstr;
2240 char *str = NULL; 2224 char *str = NULL;
2241 char *op = NULL; 2225 char *op = NULL;
2242 int len;
2243 2226
2244 lstr = arg_to_str(filter, arg->num.left); 2227 lstr = arg_to_str(filter, arg->num.left);
2245 rstr = arg_to_str(filter, arg->num.right); 2228 rstr = arg_to_str(filter, arg->num.right);
@@ -2270,10 +2253,7 @@ static char *num_to_str(struct event_filter *filter, struct filter_arg *arg)
2270 if (!op) 2253 if (!op)
2271 op = "<="; 2254 op = "<=";
2272 2255
2273 len = strlen(lstr) + strlen(op) + strlen(rstr) + 4; 2256 asprintf(&str, "%s %s %s", lstr, op, rstr);
2274 str = malloc_or_die(len);
2275 sprintf(str, "%s %s %s", lstr, op, rstr);
2276
2277 break; 2257 break;
2278 2258
2279 default: 2259 default:
@@ -2291,7 +2271,6 @@ static char *str_to_str(struct event_filter *filter, struct filter_arg *arg)
2291{ 2271{
2292 char *str = NULL; 2272 char *str = NULL;
2293 char *op = NULL; 2273 char *op = NULL;
2294 int len;
2295 2274
2296 switch (arg->str.type) { 2275 switch (arg->str.type) {
2297 case FILTER_CMP_MATCH: 2276 case FILTER_CMP_MATCH:
@@ -2309,12 +2288,8 @@ static char *str_to_str(struct event_filter *filter, struct filter_arg *arg)
2309 if (!op) 2288 if (!op)
2310 op = "!~"; 2289 op = "!~";
2311 2290
2312 len = strlen(arg->str.field->name) + strlen(op) + 2291 asprintf(&str, "%s %s \"%s\"",
2313 strlen(arg->str.val) + 6; 2292 arg->str.field->name, op, arg->str.val);
2314 str = malloc_or_die(len);
2315 snprintf(str, len, "%s %s \"%s\"",
2316 arg->str.field->name,
2317 op, arg->str.val);
2318 break; 2293 break;
2319 2294
2320 default: 2295 default:
@@ -2326,15 +2301,11 @@ static char *str_to_str(struct event_filter *filter, struct filter_arg *arg)
2326 2301
2327static char *arg_to_str(struct event_filter *filter, struct filter_arg *arg) 2302static char *arg_to_str(struct event_filter *filter, struct filter_arg *arg)
2328{ 2303{
2329 char *str; 2304 char *str = NULL;
2330 2305
2331 switch (arg->type) { 2306 switch (arg->type) {
2332 case FILTER_ARG_BOOLEAN: 2307 case FILTER_ARG_BOOLEAN:
2333 str = malloc_or_die(6); 2308 asprintf(&str, arg->boolean.value ? "TRUE" : "FALSE");
2334 if (arg->boolean.value)
2335 strcpy(str, "TRUE");
2336 else
2337 strcpy(str, "FALSE");
2338 return str; 2309 return str;
2339 2310
2340 case FILTER_ARG_OP: 2311 case FILTER_ARG_OP:
@@ -2369,7 +2340,7 @@ static char *arg_to_str(struct event_filter *filter, struct filter_arg *arg)
2369 * 2340 *
2370 * Returns a string that displays the filter contents. 2341 * Returns a string that displays the filter contents.
2371 * This string must be freed with free(str). 2342 * This string must be freed with free(str).
2372 * NULL is returned if no filter is found. 2343 * NULL is returned if no filter is found or allocation failed.
2373 */ 2344 */
2374char * 2345char *
2375pevent_filter_make_string(struct event_filter *filter, int event_id) 2346pevent_filter_make_string(struct event_filter *filter, int event_id)
diff --git a/tools/perf/Documentation/perf-timechart.txt b/tools/perf/Documentation/perf-timechart.txt
index 271dd4ed5b05..bc5990c33dc0 100644
--- a/tools/perf/Documentation/perf-timechart.txt
+++ b/tools/perf/Documentation/perf-timechart.txt
@@ -56,9 +56,25 @@ $ perf timechart
56 56
57 Written 10.2 seconds of trace to output.svg. 57 Written 10.2 seconds of trace to output.svg.
58 58
59Record system-wide timechart:
60
61 $ perf timechart record
62
63 then generate timechart and highlight 'gcc' tasks:
64
65 $ perf timechart --highlight gcc
66
59-n:: 67-n::
60--proc-num:: 68--proc-num::
61 Print task info for at least given number of tasks. 69 Print task info for at least given number of tasks.
70-t::
71--topology::
72 Sort CPUs according to topology.
73--highlight=<duration_nsecs|task_name>::
74 Highlight tasks (using different color) that run more than given
75 duration or tasks with given name. If number is given it's interpreted
76 as number of nanoseconds. If non-numeric string is given it's
77 interpreted as task name.
62 78
63RECORD OPTIONS 79RECORD OPTIONS
64-------------- 80--------------
diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
index fad61079e795..97a2145e4cc6 100644
--- a/tools/perf/Makefile.perf
+++ b/tools/perf/Makefile.perf
@@ -86,7 +86,7 @@ FLEX = flex
86BISON = bison 86BISON = bison
87STRIP = strip 87STRIP = strip
88 88
89LK_DIR = $(srctree)/tools/lib/lk/ 89LIB_DIR = $(srctree)/tools/lib/api/
90TRACE_EVENT_DIR = $(srctree)/tools/lib/traceevent/ 90TRACE_EVENT_DIR = $(srctree)/tools/lib/traceevent/
91 91
92# include config/Makefile by default and rule out 92# include config/Makefile by default and rule out
@@ -127,20 +127,20 @@ strip-libs = $(filter-out -l%,$(1))
127ifneq ($(OUTPUT),) 127ifneq ($(OUTPUT),)
128 TE_PATH=$(OUTPUT) 128 TE_PATH=$(OUTPUT)
129ifneq ($(subdir),) 129ifneq ($(subdir),)
130 LK_PATH=$(OUTPUT)/../lib/lk/ 130 LIB_PATH=$(OUTPUT)/../lib/api/
131else 131else
132 LK_PATH=$(OUTPUT) 132 LIB_PATH=$(OUTPUT)
133endif 133endif
134else 134else
135 TE_PATH=$(TRACE_EVENT_DIR) 135 TE_PATH=$(TRACE_EVENT_DIR)
136 LK_PATH=$(LK_DIR) 136 LIB_PATH=$(LIB_DIR)
137endif 137endif
138 138
139LIBTRACEEVENT = $(TE_PATH)libtraceevent.a 139LIBTRACEEVENT = $(TE_PATH)libtraceevent.a
140export LIBTRACEEVENT 140export LIBTRACEEVENT
141 141
142LIBLK = $(LK_PATH)liblk.a 142LIBAPIKFS = $(LIB_PATH)libapikfs.a
143export LIBLK 143export LIBAPIKFS
144 144
145# python extension build directories 145# python extension build directories
146PYTHON_EXTBUILD := $(OUTPUT)python_ext_build/ 146PYTHON_EXTBUILD := $(OUTPUT)python_ext_build/
@@ -151,7 +151,7 @@ export PYTHON_EXTBUILD_LIB PYTHON_EXTBUILD_TMP
151python-clean := $(call QUIET_CLEAN, python) $(RM) -r $(PYTHON_EXTBUILD) $(OUTPUT)python/perf.so 151python-clean := $(call QUIET_CLEAN, python) $(RM) -r $(PYTHON_EXTBUILD) $(OUTPUT)python/perf.so
152 152
153PYTHON_EXT_SRCS := $(shell grep -v ^\# util/python-ext-sources) 153PYTHON_EXT_SRCS := $(shell grep -v ^\# util/python-ext-sources)
154PYTHON_EXT_DEPS := util/python-ext-sources util/setup.py $(LIBTRACEEVENT) $(LIBLK) 154PYTHON_EXT_DEPS := util/python-ext-sources util/setup.py $(LIBTRACEEVENT) $(LIBAPIKFS)
155 155
156$(OUTPUT)python/perf.so: $(PYTHON_EXT_SRCS) $(PYTHON_EXT_DEPS) 156$(OUTPUT)python/perf.so: $(PYTHON_EXT_SRCS) $(PYTHON_EXT_DEPS)
157 $(QUIET_GEN)CFLAGS='$(CFLAGS)' $(PYTHON_WORD) util/setup.py \ 157 $(QUIET_GEN)CFLAGS='$(CFLAGS)' $(PYTHON_WORD) util/setup.py \
@@ -441,7 +441,7 @@ BUILTIN_OBJS += $(OUTPUT)builtin-inject.o
441BUILTIN_OBJS += $(OUTPUT)tests/builtin-test.o 441BUILTIN_OBJS += $(OUTPUT)tests/builtin-test.o
442BUILTIN_OBJS += $(OUTPUT)builtin-mem.o 442BUILTIN_OBJS += $(OUTPUT)builtin-mem.o
443 443
444PERFLIBS = $(LIB_FILE) $(LIBLK) $(LIBTRACEEVENT) 444PERFLIBS = $(LIB_FILE) $(LIBAPIKFS) $(LIBTRACEEVENT)
445 445
446# We choose to avoid "if .. else if .. else .. endif endif" 446# We choose to avoid "if .. else if .. else .. endif endif"
447# because maintaining the nesting to match is a pain. If 447# because maintaining the nesting to match is a pain. If
@@ -730,19 +730,19 @@ $(LIBTRACEEVENT)-clean:
730install-traceevent-plugins: $(LIBTRACEEVENT) 730install-traceevent-plugins: $(LIBTRACEEVENT)
731 $(QUIET_SUBDIR0)$(TRACE_EVENT_DIR) $(LIBTRACEEVENT_FLAGS) install_plugins 731 $(QUIET_SUBDIR0)$(TRACE_EVENT_DIR) $(LIBTRACEEVENT_FLAGS) install_plugins
732 732
733LIBLK_SOURCES = $(wildcard $(LK_PATH)*.[ch]) 733LIBAPIKFS_SOURCES = $(wildcard $(LIB_PATH)fs/*.[ch])
734 734
735# if subdir is set, we've been called from above so target has been built 735# if subdir is set, we've been called from above so target has been built
736# already 736# already
737$(LIBLK): $(LIBLK_SOURCES) 737$(LIBAPIKFS): $(LIBAPIKFS_SOURCES)
738ifeq ($(subdir),) 738ifeq ($(subdir),)
739 $(QUIET_SUBDIR0)$(LK_DIR) $(QUIET_SUBDIR1) O=$(OUTPUT) liblk.a 739 $(QUIET_SUBDIR0)$(LIB_DIR) $(QUIET_SUBDIR1) O=$(OUTPUT) libapikfs.a
740endif 740endif
741 741
742$(LIBLK)-clean: 742$(LIBAPIKFS)-clean:
743ifeq ($(subdir),) 743ifeq ($(subdir),)
744 $(call QUIET_CLEAN, liblk) 744 $(call QUIET_CLEAN, libapikfs)
745 @$(MAKE) -C $(LK_DIR) O=$(OUTPUT) clean >/dev/null 745 @$(MAKE) -C $(LIB_DIR) O=$(OUTPUT) clean >/dev/null
746endif 746endif
747 747
748help: 748help:
@@ -881,12 +881,11 @@ config-clean:
881 $(call QUIET_CLEAN, config) 881 $(call QUIET_CLEAN, config)
882 @$(MAKE) -C config/feature-checks clean >/dev/null 882 @$(MAKE) -C config/feature-checks clean >/dev/null
883 883
884clean: $(LIBTRACEEVENT)-clean $(LIBLK)-clean config-clean 884clean: $(LIBTRACEEVENT)-clean $(LIBAPIKFS)-clean config-clean
885 $(call QUIET_CLEAN, core-objs) $(RM) $(LIB_OBJS) $(BUILTIN_OBJS) $(LIB_FILE) $(OUTPUT)perf-archive $(OUTPUT)perf.o $(LANG_BINDINGS) $(GTK_OBJS) 885 $(call QUIET_CLEAN, core-objs) $(RM) $(LIB_OBJS) $(BUILTIN_OBJS) $(LIB_FILE) $(OUTPUT)perf-archive $(OUTPUT)perf.o $(LANG_BINDINGS) $(GTK_OBJS)
886 $(call QUIET_CLEAN, core-progs) $(RM) $(ALL_PROGRAMS) perf 886 $(call QUIET_CLEAN, core-progs) $(RM) $(ALL_PROGRAMS) perf
887 $(call QUIET_CLEAN, core-gen) $(RM) *.spec *.pyc *.pyo */*.pyc */*.pyo $(OUTPUT)common-cmds.h TAGS tags cscope* $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)PERF-CFLAGS $(OUTPUT)util/*-bison* $(OUTPUT)util/*-flex* 887 $(call QUIET_CLEAN, core-gen) $(RM) *.spec *.pyc *.pyo */*.pyc */*.pyo $(OUTPUT)common-cmds.h TAGS tags cscope* $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)PERF-CFLAGS $(OUTPUT)util/*-bison* $(OUTPUT)util/*-flex*
888 $(call QUIET_CLEAN, Documentation) 888 $(QUIET_SUBDIR0)Documentation $(QUIET_SUBDIR1) clean
889 @$(MAKE) -C Documentation O=$(OUTPUT) clean >/dev/null
890 $(python-clean) 889 $(python-clean)
891 890
892# 891#
diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c
index c6fa3cbd45a9..154b397a5d27 100644
--- a/tools/perf/builtin-kvm.c
+++ b/tools/perf/builtin-kvm.c
@@ -13,7 +13,7 @@
13#include "util/parse-options.h" 13#include "util/parse-options.h"
14#include "util/trace-event.h" 14#include "util/trace-event.h"
15#include "util/debug.h" 15#include "util/debug.h"
16#include <lk/debugfs.h> 16#include <api/fs/debugfs.h>
17#include "util/tool.h" 17#include "util/tool.h"
18#include "util/stat.h" 18#include "util/stat.h"
19#include "util/top.h" 19#include "util/top.h"
diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c
index 6ea9e85bdc00..c98ccb570509 100644
--- a/tools/perf/builtin-probe.c
+++ b/tools/perf/builtin-probe.c
@@ -37,7 +37,7 @@
37#include "util/strfilter.h" 37#include "util/strfilter.h"
38#include "util/symbol.h" 38#include "util/symbol.h"
39#include "util/debug.h" 39#include "util/debug.h"
40#include <lk/debugfs.h> 40#include <api/fs/debugfs.h>
41#include "util/parse-options.h" 41#include "util/parse-options.h"
42#include "util/probe-finder.h" 42#include "util/probe-finder.h"
43#include "util/probe-event.h" 43#include "util/probe-event.h"
diff --git a/tools/perf/builtin-timechart.c b/tools/perf/builtin-timechart.c
index 0bda620a717d..20d4212fa337 100644
--- a/tools/perf/builtin-timechart.c
+++ b/tools/perf/builtin-timechart.c
@@ -58,7 +58,8 @@ struct timechart {
58 first_time, last_time; 58 first_time, last_time;
59 bool power_only, 59 bool power_only,
60 tasks_only, 60 tasks_only,
61 with_backtrace; 61 with_backtrace,
62 topology;
62}; 63};
63 64
64struct per_pidcomm; 65struct per_pidcomm;
@@ -531,12 +532,10 @@ static int process_sample_event(struct perf_tool *tool,
531 tchart->last_time = sample->time; 532 tchart->last_time = sample->time;
532 } 533 }
533 534
534 if (sample->cpu > tchart->numcpus)
535 tchart->numcpus = sample->cpu;
536
537 if (evsel->handler != NULL) { 535 if (evsel->handler != NULL) {
538 tracepoint_handler f = evsel->handler; 536 tracepoint_handler f = evsel->handler;
539 return f(tchart, evsel, sample, cat_backtrace(event, sample, machine)); 537 return f(tchart, evsel, sample,
538 cat_backtrace(event, sample, machine));
540 } 539 }
541 540
542 return 0; 541 return 0;
@@ -837,8 +836,14 @@ static void draw_cpu_usage(struct timechart *tchart)
837 while (c) { 836 while (c) {
838 sample = c->samples; 837 sample = c->samples;
839 while (sample) { 838 while (sample) {
840 if (sample->type == TYPE_RUNNING) 839 if (sample->type == TYPE_RUNNING) {
841 svg_process(sample->cpu, sample->start_time, sample->end_time, "sample", c->comm); 840 svg_process(sample->cpu,
841 sample->start_time,
842 sample->end_time,
843 p->pid,
844 c->comm,
845 sample->backtrace);
846 }
842 847
843 sample = sample->next; 848 sample = sample->next;
844 } 849 }
@@ -1031,8 +1036,6 @@ static void write_svg_file(struct timechart *tchart, const char *filename)
1031 int count; 1036 int count;
1032 int thresh = TIME_THRESH; 1037 int thresh = TIME_THRESH;
1033 1038
1034 tchart->numcpus++;
1035
1036 if (tchart->power_only) 1039 if (tchart->power_only)
1037 tchart->proc_num = 0; 1040 tchart->proc_num = 0;
1038 1041
@@ -1062,6 +1065,37 @@ static void write_svg_file(struct timechart *tchart, const char *filename)
1062 svg_close(); 1065 svg_close();
1063} 1066}
1064 1067
1068static int process_header(struct perf_file_section *section __maybe_unused,
1069 struct perf_header *ph,
1070 int feat,
1071 int fd __maybe_unused,
1072 void *data)
1073{
1074 struct timechart *tchart = data;
1075
1076 switch (feat) {
1077 case HEADER_NRCPUS:
1078 tchart->numcpus = ph->env.nr_cpus_avail;
1079 break;
1080
1081 case HEADER_CPU_TOPOLOGY:
1082 if (!tchart->topology)
1083 break;
1084
1085 if (svg_build_topology_map(ph->env.sibling_cores,
1086 ph->env.nr_sibling_cores,
1087 ph->env.sibling_threads,
1088 ph->env.nr_sibling_threads))
1089 fprintf(stderr, "problem building topology\n");
1090 break;
1091
1092 default:
1093 break;
1094 }
1095
1096 return 0;
1097}
1098
1065static int __cmd_timechart(struct timechart *tchart, const char *output_name) 1099static int __cmd_timechart(struct timechart *tchart, const char *output_name)
1066{ 1100{
1067 const struct perf_evsel_str_handler power_tracepoints[] = { 1101 const struct perf_evsel_str_handler power_tracepoints[] = {
@@ -1087,6 +1121,11 @@ static int __cmd_timechart(struct timechart *tchart, const char *output_name)
1087 if (session == NULL) 1121 if (session == NULL)
1088 return -ENOMEM; 1122 return -ENOMEM;
1089 1123
1124 (void)perf_header__process_sections(&session->header,
1125 perf_data_file__fd(session->file),
1126 tchart,
1127 process_header);
1128
1090 if (!perf_session__has_traces(session, "timechart record")) 1129 if (!perf_session__has_traces(session, "timechart record"))
1091 goto out_delete; 1130 goto out_delete;
1092 1131
@@ -1212,6 +1251,23 @@ parse_process(const struct option *opt __maybe_unused, const char *arg,
1212 return 0; 1251 return 0;
1213} 1252}
1214 1253
1254static int
1255parse_highlight(const struct option *opt __maybe_unused, const char *arg,
1256 int __maybe_unused unset)
1257{
1258 unsigned long duration = strtoul(arg, NULL, 0);
1259
1260 if (svg_highlight || svg_highlight_name)
1261 return -1;
1262
1263 if (duration)
1264 svg_highlight = duration;
1265 else
1266 svg_highlight_name = strdup(arg);
1267
1268 return 0;
1269}
1270
1215int cmd_timechart(int argc, const char **argv, 1271int cmd_timechart(int argc, const char **argv,
1216 const char *prefix __maybe_unused) 1272 const char *prefix __maybe_unused)
1217{ 1273{
@@ -1230,6 +1286,9 @@ int cmd_timechart(int argc, const char **argv,
1230 OPT_STRING('i', "input", &input_name, "file", "input file name"), 1286 OPT_STRING('i', "input", &input_name, "file", "input file name"),
1231 OPT_STRING('o', "output", &output_name, "file", "output file name"), 1287 OPT_STRING('o', "output", &output_name, "file", "output file name"),
1232 OPT_INTEGER('w', "width", &svg_page_width, "page width"), 1288 OPT_INTEGER('w', "width", &svg_page_width, "page width"),
1289 OPT_CALLBACK(0, "highlight", NULL, "duration or task name",
1290 "highlight tasks. Pass duration in ns or process name.",
1291 parse_highlight),
1233 OPT_BOOLEAN('P', "power-only", &tchart.power_only, "output power data only"), 1292 OPT_BOOLEAN('P', "power-only", &tchart.power_only, "output power data only"),
1234 OPT_BOOLEAN('T', "tasks-only", &tchart.tasks_only, 1293 OPT_BOOLEAN('T', "tasks-only", &tchart.tasks_only,
1235 "output processes data only"), 1294 "output processes data only"),
@@ -1240,6 +1299,8 @@ int cmd_timechart(int argc, const char **argv,
1240 "Look for files with symbols relative to this directory"), 1299 "Look for files with symbols relative to this directory"),
1241 OPT_INTEGER('n', "proc-num", &tchart.proc_num, 1300 OPT_INTEGER('n', "proc-num", &tchart.proc_num,
1242 "min. number of tasks to print"), 1301 "min. number of tasks to print"),
1302 OPT_BOOLEAN('t', "topology", &tchart.topology,
1303 "sort CPUs according to topology"),
1243 OPT_END() 1304 OPT_END()
1244 }; 1305 };
1245 const char * const timechart_usage[] = { 1306 const char * const timechart_usage[] = {
diff --git a/tools/perf/perf.c b/tools/perf/perf.c
index 8b38b4e80ec2..431798a4110d 100644
--- a/tools/perf/perf.c
+++ b/tools/perf/perf.c
@@ -13,7 +13,7 @@
13#include "util/quote.h" 13#include "util/quote.h"
14#include "util/run-command.h" 14#include "util/run-command.h"
15#include "util/parse-events.h" 15#include "util/parse-events.h"
16#include <lk/debugfs.h> 16#include <api/fs/debugfs.h>
17#include <pthread.h> 17#include <pthread.h>
18 18
19const char perf_usage_string[] = 19const char perf_usage_string[] =
diff --git a/tools/perf/tests/parse-events.c b/tools/perf/tests/parse-events.c
index 3cbd10496087..e4ce8aed29d3 100644
--- a/tools/perf/tests/parse-events.c
+++ b/tools/perf/tests/parse-events.c
@@ -3,7 +3,7 @@
3#include "evsel.h" 3#include "evsel.h"
4#include "evlist.h" 4#include "evlist.h"
5#include "fs.h" 5#include "fs.h"
6#include <lk/debugfs.h> 6#include <api/fs/debugfs.h>
7#include "tests.h" 7#include "tests.h"
8#include <linux/hw_breakpoint.h> 8#include <linux/hw_breakpoint.h>
9 9
diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c
index 436922f1f9d9..4ddeecb9ff85 100644
--- a/tools/perf/util/dso.c
+++ b/tools/perf/util/dso.c
@@ -28,8 +28,9 @@ char dso__symtab_origin(const struct dso *dso)
28 return origin[dso->symtab_type]; 28 return origin[dso->symtab_type];
29} 29}
30 30
31int dso__binary_type_file(const struct dso *dso, enum dso_binary_type type, 31int dso__read_binary_type_filename(const struct dso *dso,
32 char *root_dir, char *filename, size_t size) 32 enum dso_binary_type type,
33 char *root_dir, char *filename, size_t size)
33{ 34{
34 char build_id_hex[BUILD_ID_SIZE * 2 + 1]; 35 char build_id_hex[BUILD_ID_SIZE * 2 + 1];
35 int ret = 0; 36 int ret = 0;
@@ -137,19 +138,18 @@ int dso__binary_type_file(const struct dso *dso, enum dso_binary_type type,
137 138
138static int open_dso(struct dso *dso, struct machine *machine) 139static int open_dso(struct dso *dso, struct machine *machine)
139{ 140{
140 char *root_dir = (char *) "";
141 char *name;
142 int fd; 141 int fd;
142 char *root_dir = (char *)"";
143 char *name = malloc(PATH_MAX);
143 144
144 name = malloc(PATH_MAX);
145 if (!name) 145 if (!name)
146 return -ENOMEM; 146 return -ENOMEM;
147 147
148 if (machine) 148 if (machine)
149 root_dir = machine->root_dir; 149 root_dir = machine->root_dir;
150 150
151 if (dso__binary_type_file(dso, dso->data_type, 151 if (dso__read_binary_type_filename(dso, dso->binary_type,
152 root_dir, name, PATH_MAX)) { 152 root_dir, name, PATH_MAX)) {
153 free(name); 153 free(name);
154 return -EINVAL; 154 return -EINVAL;
155 } 155 }
@@ -161,26 +161,26 @@ static int open_dso(struct dso *dso, struct machine *machine)
161 161
162int dso__data_fd(struct dso *dso, struct machine *machine) 162int dso__data_fd(struct dso *dso, struct machine *machine)
163{ 163{
164 static enum dso_binary_type binary_type_data[] = { 164 enum dso_binary_type binary_type_data[] = {
165 DSO_BINARY_TYPE__BUILD_ID_CACHE, 165 DSO_BINARY_TYPE__BUILD_ID_CACHE,
166 DSO_BINARY_TYPE__SYSTEM_PATH_DSO, 166 DSO_BINARY_TYPE__SYSTEM_PATH_DSO,
167 DSO_BINARY_TYPE__NOT_FOUND, 167 DSO_BINARY_TYPE__NOT_FOUND,
168 }; 168 };
169 int i = 0; 169 int i = 0;
170 170
171 if (dso->data_type != DSO_BINARY_TYPE__NOT_FOUND) 171 if (dso->binary_type != DSO_BINARY_TYPE__NOT_FOUND)
172 return open_dso(dso, machine); 172 return open_dso(dso, machine);
173 173
174 do { 174 do {
175 int fd; 175 int fd;
176 176
177 dso->data_type = binary_type_data[i++]; 177 dso->binary_type = binary_type_data[i++];
178 178
179 fd = open_dso(dso, machine); 179 fd = open_dso(dso, machine);
180 if (fd >= 0) 180 if (fd >= 0)
181 return fd; 181 return fd;
182 182
183 } while (dso->data_type != DSO_BINARY_TYPE__NOT_FOUND); 183 } while (dso->binary_type != DSO_BINARY_TYPE__NOT_FOUND);
184 184
185 return -EINVAL; 185 return -EINVAL;
186} 186}
@@ -475,7 +475,7 @@ struct dso *dso__new(const char *name)
475 dso->symbols[i] = dso->symbol_names[i] = RB_ROOT; 475 dso->symbols[i] = dso->symbol_names[i] = RB_ROOT;
476 dso->cache = RB_ROOT; 476 dso->cache = RB_ROOT;
477 dso->symtab_type = DSO_BINARY_TYPE__NOT_FOUND; 477 dso->symtab_type = DSO_BINARY_TYPE__NOT_FOUND;
478 dso->data_type = DSO_BINARY_TYPE__NOT_FOUND; 478 dso->binary_type = DSO_BINARY_TYPE__NOT_FOUND;
479 dso->loaded = 0; 479 dso->loaded = 0;
480 dso->rel = 0; 480 dso->rel = 0;
481 dso->sorted_by_name = 0; 481 dso->sorted_by_name = 0;
diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h
index e1cc50698137..cd7d6f078cdd 100644
--- a/tools/perf/util/dso.h
+++ b/tools/perf/util/dso.h
@@ -83,7 +83,7 @@ struct dso {
83 enum dso_kernel_type kernel; 83 enum dso_kernel_type kernel;
84 enum dso_swap_type needs_swap; 84 enum dso_swap_type needs_swap;
85 enum dso_binary_type symtab_type; 85 enum dso_binary_type symtab_type;
86 enum dso_binary_type data_type; 86 enum dso_binary_type binary_type;
87 u8 adjust_symbols:1; 87 u8 adjust_symbols:1;
88 u8 has_build_id:1; 88 u8 has_build_id:1;
89 u8 has_srcline:1; 89 u8 has_srcline:1;
@@ -128,8 +128,8 @@ void dso__read_running_kernel_build_id(struct dso *dso,
128int dso__kernel_module_get_build_id(struct dso *dso, const char *root_dir); 128int dso__kernel_module_get_build_id(struct dso *dso, const char *root_dir);
129 129
130char dso__symtab_origin(const struct dso *dso); 130char dso__symtab_origin(const struct dso *dso);
131int dso__binary_type_file(const struct dso *dso, enum dso_binary_type type, 131int dso__read_binary_type_filename(const struct dso *dso, enum dso_binary_type type,
132 char *root_dir, char *filename, size_t size); 132 char *root_dir, char *filename, size_t size);
133 133
134int dso__data_fd(struct dso *dso, struct machine *machine); 134int dso__data_fd(struct dso *dso, struct machine *machine);
135ssize_t dso__data_read_offset(struct dso *dso, struct machine *machine, 135ssize_t dso__data_read_offset(struct dso *dso, struct machine *machine,
@@ -159,14 +159,14 @@ size_t dso__fprintf(struct dso *dso, enum map_type type, FILE *fp);
159 159
160static inline bool dso__is_vmlinux(struct dso *dso) 160static inline bool dso__is_vmlinux(struct dso *dso)
161{ 161{
162 return dso->data_type == DSO_BINARY_TYPE__VMLINUX || 162 return dso->binary_type == DSO_BINARY_TYPE__VMLINUX ||
163 dso->data_type == DSO_BINARY_TYPE__GUEST_VMLINUX; 163 dso->binary_type == DSO_BINARY_TYPE__GUEST_VMLINUX;
164} 164}
165 165
166static inline bool dso__is_kcore(struct dso *dso) 166static inline bool dso__is_kcore(struct dso *dso)
167{ 167{
168 return dso->data_type == DSO_BINARY_TYPE__KCORE || 168 return dso->binary_type == DSO_BINARY_TYPE__KCORE ||
169 dso->data_type == DSO_BINARY_TYPE__GUEST_KCORE; 169 dso->binary_type == DSO_BINARY_TYPE__GUEST_KCORE;
170} 170}
171 171
172void dso__free_a2l(struct dso *dso); 172void dso__free_a2l(struct dso *dso);
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index 0b31cee34874..da3182914984 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -7,7 +7,7 @@
7 * Released under the GPL v2. (and only v2, not any later version) 7 * Released under the GPL v2. (and only v2, not any later version)
8 */ 8 */
9#include "util.h" 9#include "util.h"
10#include <lk/debugfs.h> 10#include <api/fs/debugfs.h>
11#include <poll.h> 11#include <poll.h>
12#include "cpumap.h" 12#include "cpumap.h"
13#include "thread_map.h" 13#include "thread_map.h"
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 7b510fd1f08d..01ff4cfde1f5 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -9,7 +9,7 @@
9 9
10#include <byteswap.h> 10#include <byteswap.h>
11#include <linux/bitops.h> 11#include <linux/bitops.h>
12#include <lk/debugfs.h> 12#include <api/fs/debugfs.h>
13#include <traceevent/event-parse.h> 13#include <traceevent/event-parse.h>
14#include <linux/hw_breakpoint.h> 14#include <linux/hw_breakpoint.h>
15#include <linux/perf_event.h> 15#include <linux/perf_event.h>
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 969cb8f0d88d..094c28ba2fae 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -10,7 +10,7 @@
10#include "symbol.h" 10#include "symbol.h"
11#include "cache.h" 11#include "cache.h"
12#include "header.h" 12#include "header.h"
13#include <lk/debugfs.h> 13#include <api/fs/debugfs.h>
14#include "parse-events-bison.h" 14#include "parse-events-bison.h"
15#define YY_EXTRA_TYPE int 15#define YY_EXTRA_TYPE int
16#include "parse-events-flex.h" 16#include "parse-events-flex.h"
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index d7cff57945c2..544ac1898a9f 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -40,7 +40,7 @@
40#include "color.h" 40#include "color.h"
41#include "symbol.h" 41#include "symbol.h"
42#include "thread.h" 42#include "thread.h"
43#include <lk/debugfs.h> 43#include <api/fs/debugfs.h>
44#include "trace-event.h" /* For __maybe_unused */ 44#include "trace-event.h" /* For __maybe_unused */
45#include "probe-event.h" 45#include "probe-event.h"
46#include "probe-finder.h" 46#include "probe-finder.h"
diff --git a/tools/perf/util/setup.py b/tools/perf/util/setup.py
index 58ea5ca6c255..d0aee4b9dfd4 100644
--- a/tools/perf/util/setup.py
+++ b/tools/perf/util/setup.py
@@ -25,7 +25,7 @@ cflags += ['-fno-strict-aliasing', '-Wno-write-strings', '-Wno-unused-parameter'
25build_lib = getenv('PYTHON_EXTBUILD_LIB') 25build_lib = getenv('PYTHON_EXTBUILD_LIB')
26build_tmp = getenv('PYTHON_EXTBUILD_TMP') 26build_tmp = getenv('PYTHON_EXTBUILD_TMP')
27libtraceevent = getenv('LIBTRACEEVENT') 27libtraceevent = getenv('LIBTRACEEVENT')
28liblk = getenv('LIBLK') 28libapikfs = getenv('LIBAPIKFS')
29 29
30ext_sources = [f.strip() for f in file('util/python-ext-sources') 30ext_sources = [f.strip() for f in file('util/python-ext-sources')
31 if len(f.strip()) > 0 and f[0] != '#'] 31 if len(f.strip()) > 0 and f[0] != '#']
@@ -34,7 +34,7 @@ perf = Extension('perf',
34 sources = ext_sources, 34 sources = ext_sources,
35 include_dirs = ['util/include'], 35 include_dirs = ['util/include'],
36 extra_compile_args = cflags, 36 extra_compile_args = cflags,
37 extra_objects = [libtraceevent, liblk], 37 extra_objects = [libtraceevent, libapikfs],
38 ) 38 )
39 39
40setup(name='perf', 40setup(name='perf',
diff --git a/tools/perf/util/svghelper.c b/tools/perf/util/svghelper.c
index 8b79d3ad1246..56a84f2cc46d 100644
--- a/tools/perf/util/svghelper.c
+++ b/tools/perf/util/svghelper.c
@@ -17,8 +17,11 @@
17#include <stdlib.h> 17#include <stdlib.h>
18#include <unistd.h> 18#include <unistd.h>
19#include <string.h> 19#include <string.h>
20#include <linux/bitops.h>
20 21
22#include "perf.h"
21#include "svghelper.h" 23#include "svghelper.h"
24#include "cpumap.h"
22 25
23static u64 first_time, last_time; 26static u64 first_time, last_time;
24static u64 turbo_frequency, max_freq; 27static u64 turbo_frequency, max_freq;
@@ -28,6 +31,8 @@ static u64 turbo_frequency, max_freq;
28#define SLOT_HEIGHT 25.0 31#define SLOT_HEIGHT 25.0
29 32
30int svg_page_width = 1000; 33int svg_page_width = 1000;
34u64 svg_highlight;
35const char *svg_highlight_name;
31 36
32#define MIN_TEXT_SIZE 0.01 37#define MIN_TEXT_SIZE 0.01
33 38
@@ -39,9 +44,14 @@ static double cpu2slot(int cpu)
39 return 2 * cpu + 1; 44 return 2 * cpu + 1;
40} 45}
41 46
47static int *topology_map;
48
42static double cpu2y(int cpu) 49static double cpu2y(int cpu)
43{ 50{
44 return cpu2slot(cpu) * SLOT_MULT; 51 if (topology_map)
52 return cpu2slot(topology_map[cpu]) * SLOT_MULT;
53 else
54 return cpu2slot(cpu) * SLOT_MULT;
45} 55}
46 56
47static double time2pixels(u64 __time) 57static double time2pixels(u64 __time)
@@ -104,6 +114,7 @@ void open_svg(const char *filename, int cpus, int rows, u64 start, u64 end)
104 fprintf(svgfile, " rect.process { fill:rgb(180,180,180); fill-opacity:0.9; stroke-width:1; stroke:rgb( 0, 0, 0); } \n"); 114 fprintf(svgfile, " rect.process { fill:rgb(180,180,180); fill-opacity:0.9; stroke-width:1; stroke:rgb( 0, 0, 0); } \n");
105 fprintf(svgfile, " rect.process2 { fill:rgb(180,180,180); fill-opacity:0.9; stroke-width:0; stroke:rgb( 0, 0, 0); } \n"); 115 fprintf(svgfile, " rect.process2 { fill:rgb(180,180,180); fill-opacity:0.9; stroke-width:0; stroke:rgb( 0, 0, 0); } \n");
106 fprintf(svgfile, " rect.sample { fill:rgb( 0, 0,255); fill-opacity:0.8; stroke-width:0; stroke:rgb( 0, 0, 0); } \n"); 116 fprintf(svgfile, " rect.sample { fill:rgb( 0, 0,255); fill-opacity:0.8; stroke-width:0; stroke:rgb( 0, 0, 0); } \n");
117 fprintf(svgfile, " rect.sample_hi{ fill:rgb(255,128, 0); fill-opacity:0.8; stroke-width:0; stroke:rgb( 0, 0, 0); } \n");
107 fprintf(svgfile, " rect.blocked { fill:rgb(255, 0, 0); fill-opacity:0.5; stroke-width:0; stroke:rgb( 0, 0, 0); } \n"); 118 fprintf(svgfile, " rect.blocked { fill:rgb(255, 0, 0); fill-opacity:0.5; stroke-width:0; stroke:rgb( 0, 0, 0); } \n");
108 fprintf(svgfile, " rect.waiting { fill:rgb(224,214, 0); fill-opacity:0.8; stroke-width:0; stroke:rgb( 0, 0, 0); } \n"); 119 fprintf(svgfile, " rect.waiting { fill:rgb(224,214, 0); fill-opacity:0.8; stroke-width:0; stroke:rgb( 0, 0, 0); } \n");
109 fprintf(svgfile, " rect.WAITING { fill:rgb(255,214, 48); fill-opacity:0.6; stroke-width:0; stroke:rgb( 0, 0, 0); } \n"); 120 fprintf(svgfile, " rect.WAITING { fill:rgb(255,214, 48); fill-opacity:0.6; stroke-width:0; stroke:rgb( 0, 0, 0); } \n");
@@ -147,17 +158,24 @@ void svg_blocked(int Yslot, int cpu, u64 start, u64 end, const char *backtrace)
147void svg_running(int Yslot, int cpu, u64 start, u64 end, const char *backtrace) 158void svg_running(int Yslot, int cpu, u64 start, u64 end, const char *backtrace)
148{ 159{
149 double text_size; 160 double text_size;
161 const char *type;
162
150 if (!svgfile) 163 if (!svgfile)
151 return; 164 return;
152 165
166 if (svg_highlight && end - start > svg_highlight)
167 type = "sample_hi";
168 else
169 type = "sample";
153 fprintf(svgfile, "<g>\n"); 170 fprintf(svgfile, "<g>\n");
154 171
155 fprintf(svgfile, "<title>#%d running %s</title>\n", 172 fprintf(svgfile, "<title>#%d running %s</title>\n",
156 cpu, time_to_string(end - start)); 173 cpu, time_to_string(end - start));
157 if (backtrace) 174 if (backtrace)
158 fprintf(svgfile, "<desc>Switched because:\n%s</desc>\n", backtrace); 175 fprintf(svgfile, "<desc>Switched because:\n%s</desc>\n", backtrace);
159 fprintf(svgfile, "<rect x=\"%4.8f\" width=\"%4.8f\" y=\"%4.1f\" height=\"%4.1f\" class=\"sample\"/>\n", 176 fprintf(svgfile, "<rect x=\"%4.8f\" width=\"%4.8f\" y=\"%4.1f\" height=\"%4.1f\" class=\"%s\"/>\n",
160 time2pixels(start), time2pixels(end)-time2pixels(start), Yslot * SLOT_MULT, SLOT_HEIGHT); 177 time2pixels(start), time2pixels(end)-time2pixels(start), Yslot * SLOT_MULT, SLOT_HEIGHT,
178 type);
161 179
162 text_size = (time2pixels(end)-time2pixels(start)); 180 text_size = (time2pixels(end)-time2pixels(start));
163 if (cpu > 9) 181 if (cpu > 9)
@@ -275,7 +293,7 @@ void svg_cpu_box(int cpu, u64 __max_freq, u64 __turbo_freq)
275 time2pixels(last_time)-time2pixels(first_time), 293 time2pixels(last_time)-time2pixels(first_time),
276 cpu2y(cpu), SLOT_MULT+SLOT_HEIGHT); 294 cpu2y(cpu), SLOT_MULT+SLOT_HEIGHT);
277 295
278 sprintf(cpu_string, "CPU %i", (int)cpu+1); 296 sprintf(cpu_string, "CPU %i", (int)cpu);
279 fprintf(svgfile, "<text x=\"%4.8f\" y=\"%4.8f\">%s</text>\n", 297 fprintf(svgfile, "<text x=\"%4.8f\" y=\"%4.8f\">%s</text>\n",
280 10+time2pixels(first_time), cpu2y(cpu) + SLOT_HEIGHT/2, cpu_string); 298 10+time2pixels(first_time), cpu2y(cpu) + SLOT_HEIGHT/2, cpu_string);
281 299
@@ -285,16 +303,25 @@ void svg_cpu_box(int cpu, u64 __max_freq, u64 __turbo_freq)
285 fprintf(svgfile, "</g>\n"); 303 fprintf(svgfile, "</g>\n");
286} 304}
287 305
288void svg_process(int cpu, u64 start, u64 end, const char *type, const char *name) 306void svg_process(int cpu, u64 start, u64 end, int pid, const char *name, const char *backtrace)
289{ 307{
290 double width; 308 double width;
309 const char *type;
291 310
292 if (!svgfile) 311 if (!svgfile)
293 return; 312 return;
294 313
314 if (svg_highlight && end - start >= svg_highlight)
315 type = "sample_hi";
316 else if (svg_highlight_name && strstr(name, svg_highlight_name))
317 type = "sample_hi";
318 else
319 type = "sample";
295 320
296 fprintf(svgfile, "<g transform=\"translate(%4.8f,%4.8f)\">\n", time2pixels(start), cpu2y(cpu)); 321 fprintf(svgfile, "<g transform=\"translate(%4.8f,%4.8f)\">\n", time2pixels(start), cpu2y(cpu));
297 fprintf(svgfile, "<title>%s %s</title>\n", name, time_to_string(end - start)); 322 fprintf(svgfile, "<title>%d %s running %s</title>\n", pid, name, time_to_string(end - start));
323 if (backtrace)
324 fprintf(svgfile, "<desc>Switched because:\n%s</desc>\n", backtrace);
298 fprintf(svgfile, "<rect x=\"0\" width=\"%4.8f\" y=\"0\" height=\"%4.1f\" class=\"%s\"/>\n", 325 fprintf(svgfile, "<rect x=\"0\" width=\"%4.8f\" y=\"0\" height=\"%4.1f\" class=\"%s\"/>\n",
299 time2pixels(end)-time2pixels(start), SLOT_MULT+SLOT_HEIGHT, type); 326 time2pixels(end)-time2pixels(start), SLOT_MULT+SLOT_HEIGHT, type);
300 width = time2pixels(end)-time2pixels(start); 327 width = time2pixels(end)-time2pixels(start);
@@ -566,3 +593,123 @@ void svg_close(void)
566 svgfile = NULL; 593 svgfile = NULL;
567 } 594 }
568} 595}
596
597#define cpumask_bits(maskp) ((maskp)->bits)
598typedef struct { DECLARE_BITMAP(bits, MAX_NR_CPUS); } cpumask_t;
599
600struct topology {
601 cpumask_t *sib_core;
602 int sib_core_nr;
603 cpumask_t *sib_thr;
604 int sib_thr_nr;
605};
606
607static void scan_thread_topology(int *map, struct topology *t, int cpu, int *pos)
608{
609 int i;
610 int thr;
611
612 for (i = 0; i < t->sib_thr_nr; i++) {
613 if (!test_bit(cpu, cpumask_bits(&t->sib_thr[i])))
614 continue;
615
616 for_each_set_bit(thr,
617 cpumask_bits(&t->sib_thr[i]),
618 MAX_NR_CPUS)
619 if (map[thr] == -1)
620 map[thr] = (*pos)++;
621 }
622}
623
624static void scan_core_topology(int *map, struct topology *t)
625{
626 int pos = 0;
627 int i;
628 int cpu;
629
630 for (i = 0; i < t->sib_core_nr; i++)
631 for_each_set_bit(cpu,
632 cpumask_bits(&t->sib_core[i]),
633 MAX_NR_CPUS)
634 scan_thread_topology(map, t, cpu, &pos);
635}
636
637static int str_to_bitmap(char *s, cpumask_t *b)
638{
639 int i;
640 int ret = 0;
641 struct cpu_map *m;
642 int c;
643
644 m = cpu_map__new(s);
645 if (!m)
646 return -1;
647
648 for (i = 0; i < m->nr; i++) {
649 c = m->map[i];
650 if (c >= MAX_NR_CPUS) {
651 ret = -1;
652 break;
653 }
654
655 set_bit(c, cpumask_bits(b));
656 }
657
658 cpu_map__delete(m);
659
660 return ret;
661}
662
663int svg_build_topology_map(char *sib_core, int sib_core_nr,
664 char *sib_thr, int sib_thr_nr)
665{
666 int i;
667 struct topology t;
668
669 t.sib_core_nr = sib_core_nr;
670 t.sib_thr_nr = sib_thr_nr;
671 t.sib_core = calloc(sib_core_nr, sizeof(cpumask_t));
672 t.sib_thr = calloc(sib_thr_nr, sizeof(cpumask_t));
673
674 if (!t.sib_core || !t.sib_thr) {
675 fprintf(stderr, "topology: no memory\n");
676 goto exit;
677 }
678
679 for (i = 0; i < sib_core_nr; i++) {
680 if (str_to_bitmap(sib_core, &t.sib_core[i])) {
681 fprintf(stderr, "topology: can't parse siblings map\n");
682 goto exit;
683 }
684
685 sib_core += strlen(sib_core) + 1;
686 }
687
688 for (i = 0; i < sib_thr_nr; i++) {
689 if (str_to_bitmap(sib_thr, &t.sib_thr[i])) {
690 fprintf(stderr, "topology: can't parse siblings map\n");
691 goto exit;
692 }
693
694 sib_thr += strlen(sib_thr) + 1;
695 }
696
697 topology_map = malloc(sizeof(int) * MAX_NR_CPUS);
698 if (!topology_map) {
699 fprintf(stderr, "topology: no memory\n");
700 goto exit;
701 }
702
703 for (i = 0; i < MAX_NR_CPUS; i++)
704 topology_map[i] = -1;
705
706 scan_core_topology(topology_map, &t);
707
708 return 0;
709
710exit:
711 free(t.sib_core);
712 free(t.sib_thr);
713
714 return -1;
715}
diff --git a/tools/perf/util/svghelper.h b/tools/perf/util/svghelper.h
index fad79ceeac1a..f7b4d6e699ea 100644
--- a/tools/perf/util/svghelper.h
+++ b/tools/perf/util/svghelper.h
@@ -11,7 +11,7 @@ extern void svg_waiting(int Yslot, int cpu, u64 start, u64 end, const char *back
11extern void svg_cpu_box(int cpu, u64 max_frequency, u64 turbo_frequency); 11extern void svg_cpu_box(int cpu, u64 max_frequency, u64 turbo_frequency);
12 12
13 13
14extern void svg_process(int cpu, u64 start, u64 end, const char *type, const char *name); 14extern void svg_process(int cpu, u64 start, u64 end, int pid, const char *name, const char *backtrace);
15extern void svg_cstate(int cpu, u64 start, u64 end, int type); 15extern void svg_cstate(int cpu, u64 start, u64 end, int type);
16extern void svg_pstate(int cpu, u64 start, u64 end, u64 freq); 16extern void svg_pstate(int cpu, u64 start, u64 end, u64 freq);
17 17
@@ -23,7 +23,11 @@ extern void svg_partial_wakeline(u64 start, int row1, char *desc1, int row2, cha
23extern void svg_interrupt(u64 start, int row, const char *backtrace); 23extern void svg_interrupt(u64 start, int row, const char *backtrace);
24extern void svg_text(int Yslot, u64 start, const char *text); 24extern void svg_text(int Yslot, u64 start, const char *text);
25extern void svg_close(void); 25extern void svg_close(void);
26extern int svg_build_topology_map(char *sib_core, int sib_core_nr,
27 char *sib_thr, int sib_thr_nr);
26 28
27extern int svg_page_width; 29extern int svg_page_width;
30extern u64 svg_highlight;
31extern const char *svg_highlight_name;
28 32
29#endif /* __PERF_SVGHELPER_H */ 33#endif /* __PERF_SVGHELPER_H */
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index 61eb1cddf01a..923d00040bbf 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -1089,9 +1089,9 @@ static int dso__load_kcore(struct dso *dso, struct map *map,
1089 * dso__data_read_addr(). 1089 * dso__data_read_addr().
1090 */ 1090 */
1091 if (dso->kernel == DSO_TYPE_GUEST_KERNEL) 1091 if (dso->kernel == DSO_TYPE_GUEST_KERNEL)
1092 dso->data_type = DSO_BINARY_TYPE__GUEST_KCORE; 1092 dso->binary_type = DSO_BINARY_TYPE__GUEST_KCORE;
1093 else 1093 else
1094 dso->data_type = DSO_BINARY_TYPE__KCORE; 1094 dso->binary_type = DSO_BINARY_TYPE__KCORE;
1095 dso__set_long_name(dso, strdup(kcore_filename), true); 1095 dso__set_long_name(dso, strdup(kcore_filename), true);
1096 1096
1097 close(fd); 1097 close(fd);
@@ -1258,8 +1258,8 @@ int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter)
1258 1258
1259 enum dso_binary_type symtab_type = binary_type_symtab[i]; 1259 enum dso_binary_type symtab_type = binary_type_symtab[i];
1260 1260
1261 if (dso__binary_type_file(dso, symtab_type, 1261 if (dso__read_binary_type_filename(dso, symtab_type,
1262 root_dir, name, PATH_MAX)) 1262 root_dir, name, PATH_MAX))
1263 continue; 1263 continue;
1264 1264
1265 /* Name is now the name of the next image to try */ 1265 /* Name is now the name of the next image to try */
@@ -1368,9 +1368,9 @@ int dso__load_vmlinux(struct dso *dso, struct map *map,
1368 1368
1369 if (err > 0) { 1369 if (err > 0) {
1370 if (dso->kernel == DSO_TYPE_GUEST_KERNEL) 1370 if (dso->kernel == DSO_TYPE_GUEST_KERNEL)
1371 dso->data_type = DSO_BINARY_TYPE__GUEST_VMLINUX; 1371 dso->binary_type = DSO_BINARY_TYPE__GUEST_VMLINUX;
1372 else 1372 else
1373 dso->data_type = DSO_BINARY_TYPE__VMLINUX; 1373 dso->binary_type = DSO_BINARY_TYPE__VMLINUX;
1374 dso__set_long_name(dso, vmlinux, vmlinux_allocated); 1374 dso__set_long_name(dso, vmlinux, vmlinux_allocated);
1375 dso__set_loaded(dso, map->type); 1375 dso__set_loaded(dso, map->type);
1376 pr_debug("Using %s for symbols\n", symfs_vmlinux); 1376 pr_debug("Using %s for symbols\n", symfs_vmlinux);
diff --git a/tools/perf/util/trace-event-info.c b/tools/perf/util/trace-event-info.c
index f3c9e551bd35..c354b95a2348 100644
--- a/tools/perf/util/trace-event-info.c
+++ b/tools/perf/util/trace-event-info.c
@@ -38,7 +38,7 @@
38 38
39#include "../perf.h" 39#include "../perf.h"
40#include "trace-event.h" 40#include "trace-event.h"
41#include <lk/debugfs.h> 41#include <api/fs/debugfs.h>
42#include "evsel.h" 42#include "evsel.h"
43 43
44#define VERSION "0.5" 44#define VERSION "0.5"
diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h
index a1eea3e809a3..9a2c268ad718 100644
--- a/tools/perf/util/util.h
+++ b/tools/perf/util/util.h
@@ -71,7 +71,7 @@
71#include <linux/magic.h> 71#include <linux/magic.h>
72#include "types.h" 72#include "types.h"
73#include <sys/ttydefaults.h> 73#include <sys/ttydefaults.h>
74#include <lk/debugfs.h> 74#include <api/fs/debugfs.h>
75#include <termios.h> 75#include <termios.h>
76#include <linux/bitops.h> 76#include <linux/bitops.h>
77 77
diff --git a/tools/vm/Makefile b/tools/vm/Makefile
index 24e9ddd93fa4..3d907dacf2ac 100644
--- a/tools/vm/Makefile
+++ b/tools/vm/Makefile
@@ -2,21 +2,21 @@
2# 2#
3TARGETS=page-types slabinfo 3TARGETS=page-types slabinfo
4 4
5LK_DIR = ../lib/lk 5LIB_DIR = ../lib/api
6LIBLK = $(LK_DIR)/liblk.a 6LIBS = $(LIB_DIR)/libapikfs.a
7 7
8CC = $(CROSS_COMPILE)gcc 8CC = $(CROSS_COMPILE)gcc
9CFLAGS = -Wall -Wextra -I../lib/ 9CFLAGS = -Wall -Wextra -I../lib/
10LDFLAGS = $(LIBLK) 10LDFLAGS = $(LIBS)
11 11
12$(TARGETS): liblk 12$(TARGETS): $(LIBS)
13 13
14liblk: 14$(LIBS):
15 make -C $(LK_DIR) 15 make -C $(LIB_DIR)
16 16
17%: %.c 17%: %.c
18 $(CC) $(CFLAGS) -o $@ $< $(LDFLAGS) 18 $(CC) $(CFLAGS) -o $@ $< $(LDFLAGS)
19 19
20clean: 20clean:
21 $(RM) page-types slabinfo 21 $(RM) page-types slabinfo
22 make -C ../lib/lk clean 22 make -C $(LIB_DIR) clean
diff --git a/tools/vm/page-types.c b/tools/vm/page-types.c
index d5e9d6d185c8..f9be24d9efac 100644
--- a/tools/vm/page-types.c
+++ b/tools/vm/page-types.c
@@ -36,7 +36,7 @@
36#include <sys/statfs.h> 36#include <sys/statfs.h>
37#include "../../include/uapi/linux/magic.h" 37#include "../../include/uapi/linux/magic.h"
38#include "../../include/uapi/linux/kernel-page-flags.h" 38#include "../../include/uapi/linux/kernel-page-flags.h"
39#include <lk/debugfs.h> 39#include <api/fs/debugfs.h>
40 40
41#ifndef MAX_PATH 41#ifndef MAX_PATH
42# define MAX_PATH 256 42# define MAX_PATH 256