aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/builtin-top.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/builtin-top.c')
-rw-r--r--tools/perf/builtin-top.c81
1 files changed, 48 insertions, 33 deletions
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index 5352b5e352ed..95d5c0ae375a 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -23,7 +23,7 @@
23#include "util/symbol.h" 23#include "util/symbol.h"
24#include "util/color.h" 24#include "util/color.h"
25#include "util/util.h" 25#include "util/util.h"
26#include "util/rbtree.h" 26#include <linux/rbtree.h>
27#include "util/parse-options.h" 27#include "util/parse-options.h"
28#include "util/parse-events.h" 28#include "util/parse-events.h"
29 29
@@ -66,6 +66,7 @@ static unsigned int page_size;
66static unsigned int mmap_pages = 16; 66static unsigned int mmap_pages = 16;
67static int freq = 0; 67static int freq = 0;
68static int verbose = 0; 68static int verbose = 0;
69static char *vmlinux = NULL;
69 70
70static char *sym_filter; 71static char *sym_filter;
71static unsigned long filter_start; 72static unsigned long filter_start;
@@ -238,7 +239,6 @@ static void print_sym_table(void)
238 for (nd = rb_first(&tmp); nd; nd = rb_next(nd)) { 239 for (nd = rb_first(&tmp); nd; nd = rb_next(nd)) {
239 struct sym_entry *syme = rb_entry(nd, struct sym_entry, rb_node); 240 struct sym_entry *syme = rb_entry(nd, struct sym_entry, rb_node);
240 struct symbol *sym = (struct symbol *)(syme + 1); 241 struct symbol *sym = (struct symbol *)(syme + 1);
241 char *color = PERF_COLOR_NORMAL;
242 double pcnt; 242 double pcnt;
243 243
244 if (++printed > print_entries || syme->snap_count < count_filter) 244 if (++printed > print_entries || syme->snap_count < count_filter)
@@ -247,29 +247,20 @@ static void print_sym_table(void)
247 pcnt = 100.0 - (100.0 * ((sum_ksamples - syme->snap_count) / 247 pcnt = 100.0 - (100.0 * ((sum_ksamples - syme->snap_count) /
248 sum_ksamples)); 248 sum_ksamples));
249 249
250 /*
251 * We color high-overhead entries in red, mid-overhead
252 * entries in green - and keep the low overhead places
253 * normal:
254 */
255 if (pcnt >= 5.0) {
256 color = PERF_COLOR_RED;
257 } else {
258 if (pcnt >= 0.5)
259 color = PERF_COLOR_GREEN;
260 }
261
262 if (nr_counters == 1) 250 if (nr_counters == 1)
263 printf("%20.2f - ", syme->weight); 251 printf("%20.2f - ", syme->weight);
264 else 252 else
265 printf("%9.1f %10ld - ", syme->weight, syme->snap_count); 253 printf("%9.1f %10ld - ", syme->weight, syme->snap_count);
266 254
267 color_fprintf(stdout, color, "%4.1f%%", pcnt); 255 percent_color_fprintf(stdout, "%4.1f%%", pcnt);
268 printf(" - %016llx : %s\n", sym->start, sym->name); 256 printf(" - %016llx : %s", sym->start, sym->name);
257 if (sym->module)
258 printf("\t[%s]", sym->module->name);
259 printf("\n");
269 } 260 }
270} 261}
271 262
272static void *display_thread(void *arg) 263static void *display_thread(void *arg __used)
273{ 264{
274 struct pollfd stdin_poll = { .fd = 0, .events = POLLIN }; 265 struct pollfd stdin_poll = { .fd = 0, .events = POLLIN };
275 int delay_msecs = delay_secs * 1000; 266 int delay_msecs = delay_secs * 1000;
@@ -286,11 +277,31 @@ static void *display_thread(void *arg)
286 return NULL; 277 return NULL;
287} 278}
288 279
280/* Tag samples to be skipped. */
281static const char *skip_symbols[] = {
282 "default_idle",
283 "cpu_idle",
284 "enter_idle",
285 "exit_idle",
286 "mwait_idle",
287 "ppc64_runlatch_off",
288 "pseries_dedicated_idle_sleep",
289 NULL
290};
291
289static int symbol_filter(struct dso *self, struct symbol *sym) 292static int symbol_filter(struct dso *self, struct symbol *sym)
290{ 293{
291 static int filter_match; 294 static int filter_match;
292 struct sym_entry *syme; 295 struct sym_entry *syme;
293 const char *name = sym->name; 296 const char *name = sym->name;
297 int i;
298
299 /*
300 * ppc64 uses function descriptors and appends a '.' to the
301 * start of every instruction address. Remove it.
302 */
303 if (name[0] == '.')
304 name++;
294 305
295 if (!strcmp(name, "_text") || 306 if (!strcmp(name, "_text") ||
296 !strcmp(name, "_etext") || 307 !strcmp(name, "_etext") ||
@@ -302,13 +313,12 @@ static int symbol_filter(struct dso *self, struct symbol *sym)
302 return 1; 313 return 1;
303 314
304 syme = dso__sym_priv(self, sym); 315 syme = dso__sym_priv(self, sym);
305 /* Tag samples to be skipped. */ 316 for (i = 0; skip_symbols[i]; i++) {
306 if (!strcmp("default_idle", name) || 317 if (!strcmp(skip_symbols[i], name)) {
307 !strcmp("cpu_idle", name) || 318 syme->skip = 1;
308 !strcmp("enter_idle", name) || 319 break;
309 !strcmp("exit_idle", name) || 320 }
310 !strcmp("mwait_idle", name)) 321 }
311 syme->skip = 1;
312 322
313 if (filter_match == 1) { 323 if (filter_match == 1) {
314 filter_end = sym->start; 324 filter_end = sym->start;
@@ -340,12 +350,13 @@ static int parse_symbols(void)
340{ 350{
341 struct rb_node *node; 351 struct rb_node *node;
342 struct symbol *sym; 352 struct symbol *sym;
353 int modules = vmlinux ? 1 : 0;
343 354
344 kernel_dso = dso__new("[kernel]", sizeof(struct sym_entry)); 355 kernel_dso = dso__new("[kernel]", sizeof(struct sym_entry));
345 if (kernel_dso == NULL) 356 if (kernel_dso == NULL)
346 return -1; 357 return -1;
347 358
348 if (dso__load_kernel(kernel_dso, NULL, symbol_filter, 1) != 0) 359 if (dso__load_kernel(kernel_dso, vmlinux, symbol_filter, verbose, modules) <= 0)
349 goto out_delete_dso; 360 goto out_delete_dso;
350 361
351 node = rb_first(&kernel_dso->syms); 362 node = rb_first(&kernel_dso->syms);
@@ -392,11 +403,11 @@ static void record_ip(u64 ip, int counter)
392 samples--; 403 samples--;
393} 404}
394 405
395static void process_event(u64 ip, int counter) 406static void process_event(u64 ip, int counter, int user)
396{ 407{
397 samples++; 408 samples++;
398 409
399 if (ip < min_ip || ip > max_ip) { 410 if (user) {
400 userspace_samples++; 411 userspace_samples++;
401 return; 412 return;
402 } 413 }
@@ -407,7 +418,7 @@ static void process_event(u64 ip, int counter)
407struct mmap_data { 418struct mmap_data {
408 int counter; 419 int counter;
409 void *base; 420 void *base;
410 unsigned int mask; 421 int mask;
411 unsigned int prev; 422 unsigned int prev;
412}; 423};
413 424
@@ -509,9 +520,10 @@ static void mmap_read_counter(struct mmap_data *md)
509 520
510 old += size; 521 old += size;
511 522
512 if (event->header.misc & PERF_EVENT_MISC_OVERFLOW) { 523 if (event->header.type == PERF_EVENT_SAMPLE) {
513 if (event->header.type & PERF_SAMPLE_IP) 524 int user =
514 process_event(event->ip.ip, md->counter); 525 (event->header.misc & PERF_EVENT_MISC_CPUMODE_MASK) == PERF_EVENT_MISC_USER;
526 process_event(event->ip.ip, md->counter, user);
515 } 527 }
516 } 528 }
517 529
@@ -660,6 +672,7 @@ static const struct option options[] = {
660 "system-wide collection from all CPUs"), 672 "system-wide collection from all CPUs"),
661 OPT_INTEGER('C', "CPU", &profile_cpu, 673 OPT_INTEGER('C', "CPU", &profile_cpu,
662 "CPU to profile on"), 674 "CPU to profile on"),
675 OPT_STRING('k', "vmlinux", &vmlinux, "file", "vmlinux pathname"),
663 OPT_INTEGER('m', "mmap-pages", &mmap_pages, 676 OPT_INTEGER('m', "mmap-pages", &mmap_pages,
664 "number of mmap data pages"), 677 "number of mmap data pages"),
665 OPT_INTEGER('r', "realtime", &realtime_prio, 678 OPT_INTEGER('r', "realtime", &realtime_prio,
@@ -674,7 +687,7 @@ static const struct option options[] = {
674 "put the counters into a counter group"), 687 "put the counters into a counter group"),
675 OPT_STRING('s', "sym-filter", &sym_filter, "pattern", 688 OPT_STRING('s', "sym-filter", &sym_filter, "pattern",
676 "only display symbols matchig this pattern"), 689 "only display symbols matchig this pattern"),
677 OPT_BOOLEAN('z', "zero", &group, 690 OPT_BOOLEAN('z', "zero", &zero,
678 "zero history across updates"), 691 "zero history across updates"),
679 OPT_INTEGER('F', "freq", &freq, 692 OPT_INTEGER('F', "freq", &freq,
680 "profile at this frequency"), 693 "profile at this frequency"),
@@ -685,10 +698,12 @@ static const struct option options[] = {
685 OPT_END() 698 OPT_END()
686}; 699};
687 700
688int cmd_top(int argc, const char **argv, const char *prefix) 701int cmd_top(int argc, const char **argv, const char *prefix __used)
689{ 702{
690 int counter; 703 int counter;
691 704
705 symbol__init();
706
692 page_size = sysconf(_SC_PAGE_SIZE); 707 page_size = sysconf(_SC_PAGE_SIZE);
693 708
694 argc = parse_options(argc, argv, options, top_usage, 0); 709 argc = parse_options(argc, argv, options, top_usage, 0);