From b74d12d598143c2dd30b9cb9636a50dded4cc49f Mon Sep 17 00:00:00 2001 From: Kim Phillips Date: Tue, 27 Mar 2018 06:09:56 -0500 Subject: [PATCH 01/36] perf tools: Add a "dso_size" sort order Add DSO size to perf report/top sort output list. This includes adding a map__size fn to map.h, which is approximately equal to the DSO data file_size: DSO file size map (end-start) file / (end-start) libwebkit2gtk-4.0.so.37.24.9 43260072 41295872 95% libglib-2.0.so.0.5400.1 1125680 1118208 99% libc-2.26.so 1960656 1925120 101% libdbus-1.so.3.14.13 309456 303104 102% Sample output: $ ./perf report -s dso_size,dso Samples: 2K of event 'cycles:uppp', Event count (approx.): 128373340 Overhead DSO size Shared Object 90.62% unknown [unknown] 2.87% 1118208 libglib-2.0.so.0.5400.1 1.92% 303104 libdbus-1.so.3.14.13 1.42% 1925120 libc-2.26.so 0.77% 41295872 libwebkit2gtk-4.0.so.37.24.9 0.61% 335872 libgobject-2.0.so.0.5400.1 0.41% 1052672 libgdk-3.so.0.2200.25 0.36% 106496 libpthread-2.26.so 0.29% 221184 dbus-daemon 0.17% 159744 ld-2.26.so 0.13% 49152 libwayland-client.so.0.3.0 0.12% 1642496 libgio-2.0.so.0.5400.1 0.09% 7327744 libgtk-3.so.0.2200.25 0.09% 12324864 libmozjs-52.so.0.0.0 0.05% 4796416 perf 0.04% 843776 libgjs.so.0.0.0 0.03% 1409024 libmutter-clutter-1.so Committer testing: To sort by DSO size, use: # perf report -F dso_size,dso,overhead -s dso_size 3465216 libdns-export.so.174.0.1 0.00% 3522560 libgc.so.1.0.3 0.00% 3538944 libbfd-2.29-13.fc27.so 0.59% 3670016 libunistring.so.2.1.0 0.00% 3723264 libguile-2.0.so.22.8.1 0.00% 3776512 libgio-2.0.so.0.5400.3 0.00% 3891200 libc-2.26.so 0.96% 3944448 libmozjs-17.0.so 0.00% 4218880 libperl.so.5.26.1 0.18% 4452352 libpython2.7.so.1.0 0.02% 4472832 perf 0.02% 4603904 git 0.01% 4751360 libcrypto.so.1.1.0g 0.00% 5005312 libslang.so.2.3.1 0.00% 7315456 libgtk-3.so.0.2200.26 0.09% 8818688 i965_dri.so 2.46% 8818688 i965_dri.so (deleted) 1.26% 12414976 libmozjs-52.so.0.0.0 0.03% 23642112 cc1 2.02% 27889664 [kernel.kallsyms] 25.41% 80834560 libxul.so (deleted) 15.68% 98078720 chrome 32.03% 1056964608 [kernel.kallsyms] 1.59% # Signed-off-by: Kim Phillips Tested-by: Arnaldo Carvalho de Melo Cc: Alexander Shishkin Cc: Andi Kleen Cc: Jin Yao Cc: Jiri Olsa Cc: Maxim Kuvyrkov Cc: Milian Wolff Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20180327060956.1c01ebe67a2a941bb4468c6f@arm.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/Documentation/perf-report.txt | 1 + tools/perf/util/hist.h | 1 + tools/perf/util/map.h | 4 +++ tools/perf/util/sort.c | 41 ++++++++++++++++++++++++ tools/perf/util/sort.h | 1 + 5 files changed, 48 insertions(+) diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Documentation/perf-report.txt index e1a660e60849..917e36fde6d8 100644 --- a/tools/perf/Documentation/perf-report.txt +++ b/tools/perf/Documentation/perf-report.txt @@ -80,6 +80,7 @@ OPTIONS - comm: command (name) of the task which can be read via /proc//comm - pid: command and tid of the task - dso: name of library or module executed at the time of sample + - dso_size: size of library or module executed at the time of sample - symbol: name of function executed at the time of sample - symbol_size: size of function executed at the time of sample - parent: name of function matched to the parent regex filter. Unmatched diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h index e869cad4d89f..32fbf26e0c18 100644 --- a/tools/perf/util/hist.h +++ b/tools/perf/util/hist.h @@ -61,6 +61,7 @@ enum hist_column { HISTC_SRCLINE_TO, HISTC_TRACE, HISTC_SYM_SIZE, + HISTC_DSO_SIZE, HISTC_NR_COLS, /* Last entry */ }; diff --git a/tools/perf/util/map.h b/tools/perf/util/map.h index edeb7291c8e1..0e9bbe01b0ab 100644 --- a/tools/perf/util/map.h +++ b/tools/perf/util/map.h @@ -103,6 +103,10 @@ static inline u64 identity__map_ip(struct map *map __maybe_unused, u64 ip) return ip; } +static inline size_t map__size(const struct map *map) +{ + return map->end - map->start; +} /* rip/ip <-> addr suitable for passing to `objdump --start-address=` */ u64 map__rip_2objdump(struct map *map, u64 rip); diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c index e8514f651865..26a68dfd8a4f 100644 --- a/tools/perf/util/sort.c +++ b/tools/perf/util/sort.c @@ -1545,6 +1545,46 @@ struct sort_entry sort_sym_size = { .se_width_idx = HISTC_SYM_SIZE, }; +/* --sort dso_size */ + +static int64_t _sort__dso_size_cmp(struct map *map_l, struct map *map_r) +{ + int64_t size_l = map_l != NULL ? map__size(map_l) : 0; + int64_t size_r = map_r != NULL ? map__size(map_r) : 0; + + return size_l < size_r ? -1 : + size_l == size_r ? 0 : 1; +} + +static int64_t +sort__dso_size_cmp(struct hist_entry *left, struct hist_entry *right) +{ + return _sort__dso_size_cmp(right->ms.map, left->ms.map); +} + +static int _hist_entry__dso_size_snprintf(struct map *map, char *bf, + size_t bf_size, unsigned int width) +{ + if (map && map->dso) + return repsep_snprintf(bf, bf_size, "%*d", width, + map__size(map)); + + return repsep_snprintf(bf, bf_size, "%*s", width, "unknown"); +} + +static int hist_entry__dso_size_snprintf(struct hist_entry *he, char *bf, + size_t size, unsigned int width) +{ + return _hist_entry__dso_size_snprintf(he->ms.map, bf, size, width); +} + +struct sort_entry sort_dso_size = { + .se_header = "DSO size", + .se_cmp = sort__dso_size_cmp, + .se_snprintf = hist_entry__dso_size_snprintf, + .se_width_idx = HISTC_DSO_SIZE, +}; + struct sort_dimension { const char *name; @@ -1569,6 +1609,7 @@ static struct sort_dimension common_sort_dimensions[] = { DIM(SORT_TRANSACTION, "transaction", sort_transaction), DIM(SORT_TRACE, "trace", sort_trace), DIM(SORT_SYM_SIZE, "symbol_size", sort_sym_size), + DIM(SORT_DSO_SIZE, "dso_size", sort_dso_size), DIM(SORT_CGROUP_ID, "cgroup_id", sort_cgroup_id), }; diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h index f5901c10a563..035b62e2c60b 100644 --- a/tools/perf/util/sort.h +++ b/tools/perf/util/sort.h @@ -220,6 +220,7 @@ enum sort_type { SORT_TRANSACTION, SORT_TRACE, SORT_SYM_SIZE, + SORT_DSO_SIZE, SORT_CGROUP_ID, /* branch stack specific sort keys */ From 5e2a146bbdae6095b13bca9ebe26a867030ae010 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Thu, 29 Mar 2018 11:46:53 -0300 Subject: [PATCH 02/36] tools headers: Synchronize x86's cpufeatures.h Due to these commits: 1da961d72ab0 ("x86/cpufeatures: Add Intel Total Memory Encryption cpufeature") 7958b2246fad ("x86/cpufeatures: Add Intel PCONFIG cpufeature") To silence this perf build warning: Warning: Kernel ABI header at 'tools/arch/x86/include/asm/cpufeatures.h' differs from latest version at 'arch/x86/include/asm/cpufeatures.h' Nothing in those csets requires changes in tools/perf/, so just sync it to silence the build. Cc: Adrian Hunter Cc: David Ahern Cc: Jiri Olsa Cc: Kirill A. Shutemov Cc: Namhyung Kim Cc: Wang Nan Link: https://lkml.kernel.org/n/tip-m2yl8wj0uxs8pncq2ncfcx46@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/arch/x86/include/asm/cpufeatures.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/arch/x86/include/asm/cpufeatures.h b/tools/arch/x86/include/asm/cpufeatures.h index f41079da38c5..d554c11e01ff 100644 --- a/tools/arch/x86/include/asm/cpufeatures.h +++ b/tools/arch/x86/include/asm/cpufeatures.h @@ -316,6 +316,7 @@ #define X86_FEATURE_VPCLMULQDQ (16*32+10) /* Carry-Less Multiplication Double Quadword */ #define X86_FEATURE_AVX512_VNNI (16*32+11) /* Vector Neural Network Instructions */ #define X86_FEATURE_AVX512_BITALG (16*32+12) /* Support for VPOPCNT[B,W] and VPSHUF-BITQMB instructions */ +#define X86_FEATURE_TME (16*32+13) /* Intel Total Memory Encryption */ #define X86_FEATURE_AVX512_VPOPCNTDQ (16*32+14) /* POPCNT for vectors of DW/QW */ #define X86_FEATURE_LA57 (16*32+16) /* 5-level page tables */ #define X86_FEATURE_RDPID (16*32+22) /* RDPID instruction */ @@ -328,6 +329,7 @@ /* Intel-defined CPU features, CPUID level 0x00000007:0 (EDX), word 18 */ #define X86_FEATURE_AVX512_4VNNIW (18*32+ 2) /* AVX-512 Neural Network Instructions */ #define X86_FEATURE_AVX512_4FMAPS (18*32+ 3) /* AVX-512 Multiply Accumulation Single precision */ +#define X86_FEATURE_PCONFIG (18*32+18) /* Intel PCONFIG */ #define X86_FEATURE_SPEC_CTRL (18*32+26) /* "" Speculation Control (IBRS + IBPB) */ #define X86_FEATURE_INTEL_STIBP (18*32+27) /* "" Single Thread Indirect Branch Predictors */ #define X86_FEATURE_ARCH_CAPABILITIES (18*32+29) /* IA32_ARCH_CAPABILITIES MSR (Intel) */ From 0a6545bda2756807a089c64352edfc5628c57e6c Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Thu, 29 Mar 2018 12:22:59 -0300 Subject: [PATCH 03/36] perf trace: Show only failing syscalls For instance: # perf probe "vfs_getname=getname_flags:72 pathname=result->name:string" Added new event: probe:vfs_getname (on getname_flags:72 with pathname=result->name:string) You can now use it in all perf tools, such as: perf record -e probe:vfs_getname -aR sleep 1 # perf trace --failure sleep 1 0.043 ( 0.010 ms): sleep/10978 access(filename: /etc/ld.so.preload, mode: R) = -1 ENOENT No such file or directory For reference, here are all the syscalls in this case: # perf trace sleep 1 ? ( ): sleep/10976 ... [continued]: execve()) = 0 0.027 ( 0.001 ms): sleep/10976 brk() = 0x55bdc2d04000 0.044 ( 0.010 ms): sleep/10976 access(filename: /etc/ld.so.preload, mode: R) = -1 ENOENT No such file or directory 0.057 ( 0.006 ms): sleep/10976 openat(dfd: CWD, filename: /etc/ld.so.cache, flags: CLOEXEC) = 3 0.064 ( 0.002 ms): sleep/10976 fstat(fd: 3, statbuf: 0x7fffac22b370) = 0 0.067 ( 0.003 ms): sleep/10976 mmap(len: 111457, prot: READ, flags: PRIVATE, fd: 3) = 0x7feec8615000 0.071 ( 0.001 ms): sleep/10976 close(fd: 3) = 0 0.080 ( 0.007 ms): sleep/10976 openat(dfd: CWD, filename: /lib64/libc.so.6, flags: CLOEXEC) = 3 0.088 ( 0.002 ms): sleep/10976 read(fd: 3, buf: 0x7fffac22b538, count: 832) = 832 0.092 ( 0.001 ms): sleep/10976 fstat(fd: 3, statbuf: 0x7fffac22b3d0) = 0 0.094 ( 0.002 ms): sleep/10976 mmap(len: 8192, prot: READ|WRITE, flags: PRIVATE|ANONYMOUS) = 0x7feec8613000 0.099 ( 0.004 ms): sleep/10976 mmap(len: 3889792, prot: EXEC|READ, flags: PRIVATE|DENYWRITE, fd: 3) = 0x7feec8057000 0.104 ( 0.007 ms): sleep/10976 mprotect(start: 0x7feec8203000, len: 2097152) = 0 0.112 ( 0.005 ms): sleep/10976 mmap(addr: 0x7feec8403000, len: 24576, prot: READ|WRITE, flags: PRIVATE|DENYWRITE|FIXED, fd: 3, off: 1753088) = 0x7feec8403000 0.120 ( 0.003 ms): sleep/10976 mmap(addr: 0x7feec8409000, len: 14976, prot: READ|WRITE, flags: PRIVATE|ANONYMOUS|FIXED) = 0x7feec8409000 0.128 ( 0.001 ms): sleep/10976 close(fd: 3) = 0 0.139 ( 0.001 ms): sleep/10976 arch_prctl(option: 4098, arg2: 140663540761856) = 0 0.186 ( 0.004 ms): sleep/10976 mprotect(start: 0x7feec8403000, len: 16384, prot: READ) = 0 0.204 ( 0.003 ms): sleep/10976 mprotect(start: 0x55bdc0ec3000, len: 4096, prot: READ) = 0 0.209 ( 0.004 ms): sleep/10976 mprotect(start: 0x7feec8631000, len: 4096, prot: READ) = 0 0.214 ( 0.010 ms): sleep/10976 munmap(addr: 0x7feec8615000, len: 111457) = 0 0.269 ( 0.001 ms): sleep/10976 brk() = 0x55bdc2d04000 0.271 ( 0.002 ms): sleep/10976 brk(brk: 0x55bdc2d25000) = 0x55bdc2d25000 0.274 ( 0.001 ms): sleep/10976 brk() = 0x55bdc2d25000 0.278 ( 0.007 ms): sleep/10976 open(filename: /usr/lib/locale/locale-archive, flags: CLOEXEC) = 3 0.288 ( 0.001 ms): sleep/10976 fstat(fd: 3, statbuf: 0x7feec8408aa0) = 0 0.290 ( 0.003 ms): sleep/10976 mmap(len: 113045344, prot: READ, flags: PRIVATE, fd: 3) = 0x7feec1488000 0.297 ( 0.001 ms): sleep/10976 close(fd: 3) = 0 0.325 (1000.193 ms): sleep/10976 nanosleep(rqtp: 0x7fffac22c0b0) = 0 1000.560 ( 0.006 ms): sleep/10976 close(fd: 1) = 0 1000.573 ( 0.005 ms): sleep/10976 close(fd: 2) = 0 1000.596 ( ): sleep/10976 exit_group() # And can be done systemwide, etc, with backtraces: # perf trace --max-stack=16 --failure sleep 1 0.048 ( 0.015 ms): sleep/11092 access(filename: /etc/ld.so.preload, mode: R) = -1 ENOENT No such file or directory __access (inlined) dl_main (/usr/lib64/ld-2.26.so) # Or for some specific syscalls: # perf trace --max-stack=16 -e openat --failure cat /tmp/rien cat: /tmp/rien: No such file or directory 0.251 ( 0.012 ms): cat/11106 openat(dfd: CWD, filename: /tmp/rien) = -1 ENOENT No such file or directory __libc_open64 (inlined) main (/usr/bin/cat) __libc_start_main (/usr/lib64/libc-2.26.so) _start (/usr/bin/cat) # Look for inotify* syscalls that fail, system wide, for 2 seconds, with backtraces: # perf trace -a --max-stack=16 --failure -e inotify* sleep 2 819.165 ( 0.058 ms): gmain/1724 inotify_add_watch(fd: 8, pathname: /home/acme/~, mask: 16789454) = -1 ENOENT No such file or directory __GI_inotify_add_watch (inlined) _ik_watch (/usr/lib64/libgio-2.0.so.0.5400.3) _ip_start_watching (/usr/lib64/libgio-2.0.so.0.5400.3) im_scan_missing (/usr/lib64/libgio-2.0.so.0.5400.3) g_timeout_dispatch (/usr/lib64/libglib-2.0.so.0.5400.3) g_main_context_dispatch (/usr/lib64/libglib-2.0.so.0.5400.3) g_main_context_iterate.isra.23 (/usr/lib64/libglib-2.0.so.0.5400.3) g_main_context_iteration (/usr/lib64/libglib-2.0.so.0.5400.3) glib_worker_main (/usr/lib64/libglib-2.0.so.0.5400.3) g_thread_proxy (/usr/lib64/libglib-2.0.so.0.5400.3) start_thread (/usr/lib64/libpthread-2.26.so) __GI___clone (inlined) # Cc: Adrian Hunter Cc: David Ahern Cc: Jiri Olsa Cc: Namhyung Kim Cc: Wang Nan Link: https://lkml.kernel.org/n/tip-8f7d3mngaxvi7tlzloz3n7cs@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/Documentation/perf-trace.txt | 3 +++ tools/perf/builtin-trace.c | 9 ++++++--- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/tools/perf/Documentation/perf-trace.txt b/tools/perf/Documentation/perf-trace.txt index 5a7035c5c523..115db9e06ecd 100644 --- a/tools/perf/Documentation/perf-trace.txt +++ b/tools/perf/Documentation/perf-trace.txt @@ -117,6 +117,9 @@ the thread executes on the designated CPUs. Default is to monitor all CPUs. --sched:: Accrue thread runtime and provide a summary at the end of the session. +--failure:: + Show only syscalls that failed, i.e. that returned < 0. + -i:: --input:: Process events from a given perf data file. diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 87b95c9410b4..4e03f0f68241 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -112,6 +112,7 @@ struct trace { bool multiple_threads; bool summary; bool summary_only; + bool failure_only; bool show_comm; bool print_sample; bool show_tool_stats; @@ -1565,7 +1566,7 @@ static int trace__printf_interrupted_entry(struct trace *trace) struct thread_trace *ttrace; size_t printed; - if (trace->current == NULL) + if (trace->failure_only || trace->current == NULL) return 0; ttrace = thread__priv(trace->current); @@ -1638,7 +1639,7 @@ static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel, args, trace, thread); if (sc->is_exit) { - if (!(trace->duration_filter || trace->summary_only || trace->min_stack)) { + if (!(trace->duration_filter || trace->summary_only || trace->failure_only || trace->min_stack)) { trace__fprintf_entry_head(trace, thread, 0, false, ttrace->entry_time, trace->output); fprintf(trace->output, "%-70s)\n", ttrace->entry_str); } @@ -1742,7 +1743,7 @@ static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel, } } - if (trace->summary_only) + if (trace->summary_only || (ret >= 0 && trace->failure_only)) goto out; trace__fprintf_entry_head(trace, thread, duration, duration_calculated, ttrace->entry_time, trace->output); @@ -3087,6 +3088,8 @@ int cmd_trace(int argc, const char **argv) OPT_INCR('v', "verbose", &verbose, "be more verbose"), OPT_BOOLEAN('T', "time", &trace.full_time, "Show full timestamp, not time relative to first start"), + OPT_BOOLEAN(0, "failure", &trace.failure_only, + "Show only syscalls that failed"), OPT_BOOLEAN('s', "summary", &trace.summary_only, "Show only syscall summary with statistics"), OPT_BOOLEAN('S', "with-summary", &trace.summary, From 6b416ebcc32c5753214d53c18ac5719c93bc340e Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Fri, 30 Mar 2018 17:27:11 +0800 Subject: [PATCH 04/36] tools include: Add config.h header file Adding IS_BUILTIN macro and its dependencies into tools world. It's taken from kernel's include/linux/kconfig.h, which can't be taken completely due to its kconfig dependencies. Signed-off-by: Jiri Olsa Cc: Alexander Shishkin Cc: Andi Kleen Cc: Jin Yao Cc: Kan Liang Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1522402036-22915-2-git-send-email-yao.jin@linux.intel.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/include/tools/config.h | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 tools/include/tools/config.h diff --git a/tools/include/tools/config.h b/tools/include/tools/config.h new file mode 100644 index 000000000000..08ade7df8132 --- /dev/null +++ b/tools/include/tools/config.h @@ -0,0 +1,34 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _TOOLS_CONFIG_H +#define _TOOLS_CONFIG_H + +/* Subset of include/linux/kconfig.h */ + +#define __ARG_PLACEHOLDER_1 0, +#define __take_second_arg(__ignored, val, ...) val + +/* + * Helper macros to use CONFIG_ options in C/CPP expressions. Note that + * these only work with boolean and tristate options. + */ + +/* + * Getting something that works in C and CPP for an arg that may or may + * not be defined is tricky. Here, if we have "#define CONFIG_BOOGER 1" + * we match on the placeholder define, insert the "0," for arg1 and generate + * the triplet (0, 1, 0). Then the last step cherry picks the 2nd arg (a one). + * When CONFIG_BOOGER is not defined, we generate a (... 1, 0) pair, and when + * the last step cherry picks the 2nd arg, we get a zero. + */ +#define __is_defined(x) ___is_defined(x) +#define ___is_defined(val) ____is_defined(__ARG_PLACEHOLDER_##val) +#define ____is_defined(arg1_or_junk) __take_second_arg(arg1_or_junk 1, 0) + +/* + * IS_BUILTIN(CONFIG_FOO) evaluates to 1 if CONFIG_FOO is set to 'y', 0 + * otherwise. For boolean options, this is equivalent to + * IS_ENABLED(CONFIG_FOO). + */ +#define IS_BUILTIN(option) __is_defined(option) + +#endif /* _TOOLS_CONFIG_H */ From 8e2c241f0c9768c589319ff48d007526465374d2 Mon Sep 17 00:00:00 2001 From: Jin Yao Date: Fri, 30 Mar 2018 17:27:12 +0800 Subject: [PATCH 05/36] perf config: Add some new -DHAVE_XXX to CFLAGS For most of libraries, in perf.config, they are recorded with -DHAVE_XXX in CFLAGS according to if the libraries are compiled-in. Then C code then will know if the library is compiled-in or not. While for glibc, no -DHAVE_GLIBC_SUPPORT exists. For python and perl libraries, only -DNO_PYTHON and -DNO_LIBPERL exist. To make the code more consistent, the patch creates -DHAVE_LIBPYTHON_SUPPORT and -DHAVE_LIBPERL_SUPPORT if the python and perl libraries are compiled-in. Since the existing flags -DNO_PYTHON and -DNO_LIBPERL are being used in many places in C code, this patch doesn't remove them. In a follow-up patch, we will recontruct the C code and then use HAVE_XXX instead. v3: Move 'CFLAGS += -DHAVE_LIBPYTHON_SUPPORT' and 'CFLAGS += -DHAVE_LIBPERL_SUPPORT' to other places to avoid duplicated feature checking. v2: Create -DHAVE_GLIBC_SUPPORT, -DHAVE_LIBPYTHON_SUPPORT and -DHAVE_LIBPERL_SUPPORT. Signed-off-by: Jin Yao Acked-by: Jiri Olsa Cc: Alexander Shishkin Cc: Andi Kleen Cc: Jin Yao Cc: Kan Liang Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1522402036-22915-3-git-send-email-yao.jin@linux.intel.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/Makefile.config | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tools/perf/Makefile.config b/tools/perf/Makefile.config index 98ff73648b51..deb8fba2f4f1 100644 --- a/tools/perf/Makefile.config +++ b/tools/perf/Makefile.config @@ -352,6 +352,10 @@ else endif # libelf support endif # NO_LIBELF +ifeq ($(feature-glibc), 1) + CFLAGS += -DHAVE_GLIBC_SUPPORT +endif + ifdef NO_DWARF NO_LIBDW_DWARF_UNWIND := 1 endif @@ -635,6 +639,7 @@ else else LDFLAGS += $(PERL_EMBED_LDFLAGS) EXTLIBS += $(PERL_EMBED_LIBADD) + CFLAGS += -DHAVE_LIBPERL_SUPPORT $(call detected,CONFIG_LIBPERL) endif endif @@ -671,6 +676,7 @@ else LDFLAGS += $(PYTHON_EMBED_LDFLAGS) EXTLIBS += $(PYTHON_EMBED_LIBADD) LANG_BINDINGS += $(obj-perf)python/perf.so + CFLAGS += -DHAVE_LIBPYTHON_SUPPORT $(call detected,CONFIG_LIBPYTHON) endif endif From a36ebe4e242a2f6818f424b03a5e8dae3964e458 Mon Sep 17 00:00:00 2001 From: Jin Yao Date: Fri, 30 Mar 2018 17:27:13 +0800 Subject: [PATCH 06/36] perf config: Rename to HAVE_DWARF_GETLOCATIONS_SUPPORT In Makefile.config, to make all libraries flags have _SUPPORT suffix, rename HAVE_DWARF_GETLOCATIONS to HAVE_DWARF_GETLOCATIONS_SUPPORT Signed-off-by: Jin Yao Suggested-by: Ingo Molnar Acked-by: Jiri Olsa Cc: Alexander Shishkin Cc: Andi Kleen Cc: Jin Yao Cc: Kan Liang Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1522402036-22915-4-git-send-email-yao.jin@linux.intel.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/Makefile.config | 2 +- tools/perf/util/dwarf-aux.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/perf/Makefile.config b/tools/perf/Makefile.config index deb8fba2f4f1..c7abd83a8e19 100644 --- a/tools/perf/Makefile.config +++ b/tools/perf/Makefile.config @@ -346,7 +346,7 @@ else ifneq ($(feature-dwarf_getlocations), 1) msg := $(warning Old libdw.h, finding variables at given 'perf probe' point will not work, install elfutils-devel/libdw-dev >= 0.157); else - CFLAGS += -DHAVE_DWARF_GETLOCATIONS + CFLAGS += -DHAVE_DWARF_GETLOCATIONS_SUPPORT endif # dwarf_getlocations endif # Dwarf support endif # libelf support diff --git a/tools/perf/util/dwarf-aux.c b/tools/perf/util/dwarf-aux.c index f5acda13dcfa..7eb7de5aee44 100644 --- a/tools/perf/util/dwarf-aux.c +++ b/tools/perf/util/dwarf-aux.c @@ -979,7 +979,7 @@ int die_get_varname(Dwarf_Die *vr_die, struct strbuf *buf) return ret < 0 ? ret : strbuf_addf(buf, "\t%s", dwarf_diename(vr_die)); } -#ifdef HAVE_DWARF_GETLOCATIONS +#ifdef HAVE_DWARF_GETLOCATIONS_SUPPORT /** * die_get_var_innermost_scope - Get innermost scope range of given variable DIE * @sp_die: a subprogram DIE From 9ff2a64708a642b3dee867d0a083171077663b0a Mon Sep 17 00:00:00 2001 From: Jin Yao Date: Fri, 30 Mar 2018 17:27:14 +0800 Subject: [PATCH 07/36] perf version: Print the compiled-in status of libraries This patch checks the values passed by CFLAGS (-DHAVE_XXX) and then print the status of libraries. For example, if HAVE_DWARF_SUPPORT is defined, that means the library "dwarf" is compiled-in. The patch will print the status "on" for this library otherwise it print the status "OFF". A new option '--build-options' created for 'perf version' supports the printing of library status. For example: $ ./perf version --build-options or ./perf --version --build-options or ./perf -v --build-options perf version 4.13.rc5.g6727c5 dwarf: [ on ] # HAVE_DWARF_SUPPORT dwarf_getlocations: [ on ] # HAVE_DWARF_GETLOCATIONS_SUPPORT glibc: [ on ] # HAVE_GLIBC_SUPPORT gtk2: [ on ] # HAVE_GTK2_SUPPORT libaudit: [ OFF ] # HAVE_LIBAUDIT_SUPPORT libbfd: [ on ] # HAVE_LIBBFD_SUPPORT libelf: [ on ] # HAVE_LIBELF_SUPPORT libnuma: [ on ] # HAVE_LIBNUMA_SUPPORT numa_num_possible_cpus: [ on ] # HAVE_LIBNUMA_SUPPORT libperl: [ on ] # HAVE_LIBPERL_SUPPORT libpython: [ on ] # HAVE_LIBPYTHON_SUPPORT libslang: [ on ] # HAVE_SLANG_SUPPORT libcrypto: [ on ] # HAVE_LIBCRYPTO_SUPPORT libunwind: [ on ] # HAVE_LIBUNWIND_SUPPORT libdw-dwarf-unwind: [ on ] # HAVE_DWARF_SUPPORT zlib: [ on ] # HAVE_ZLIB_SUPPORT lzma: [ on ] # HAVE_LZMA_SUPPORT get_cpuid: [ on ] # HAVE_AUXTRACE_SUPPORT bpf: [ on ] # HAVE_LIBBPF_SUPPORT v4: 1. Also print the macro name. That would make it easier to grep around in the source looking for where code related a particular features is located. 2. Update since HAVE_DWARF_GETLOCATIONS is renamed to HAVE_DWARF_GETLOCATIONS_SUPPORT v3: Remove following unnecessary help message. 1. [ on ]: library is compiled-in [ OFF ]: library is disabled in make configuration OR library is not installed in build environment 2. Create '--build-options' option. 3. Use standard option parsing API 'parse_options'. v2: 1. Use IS_BUILTIN macro to replace #ifdef/#endif block. 2. Print color for on/OFF. Signed-off-by: Jin Yao Suggested-by: Arnaldo Carvalho de Melo Suggested-by: Ingo Molnar Suggested-by: Jiri Olsa Tested-by: Arnaldo Carvalho de Melo Acked-by: Jiri Olsa Cc: Alexander Shishkin Cc: Andi Kleen Cc: Jin Yao Cc: Kan Liang Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1522402036-22915-5-git-send-email-yao.jin@linux.intel.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-version.c | 82 +++++++++++++++++++++++++++++++++++- 1 file changed, 81 insertions(+), 1 deletion(-) diff --git a/tools/perf/builtin-version.c b/tools/perf/builtin-version.c index 37019c5d675f..2abe3910d6b6 100644 --- a/tools/perf/builtin-version.c +++ b/tools/perf/builtin-version.c @@ -1,11 +1,91 @@ // SPDX-License-Identifier: GPL-2.0 #include "builtin.h" #include "perf.h" +#include "color.h" #include +#include #include +#include +#include -int cmd_version(int argc __maybe_unused, const char **argv __maybe_unused) +int version_verbose; + +struct version { + bool build_options; +}; + +static struct version version; + +static struct option version_options[] = { + OPT_BOOLEAN(0, "build-options", &version.build_options, + "display the build options"), +}; + +static const char * const version_usage[] = { + "perf version []", + NULL +}; + +static void on_off_print(const char *status) { + printf("[ "); + + if (!strcmp(status, "OFF")) + color_fprintf(stdout, PERF_COLOR_RED, "%-3s", status); + else + color_fprintf(stdout, PERF_COLOR_GREEN, "%-3s", status); + + printf(" ]"); +} + +static void status_print(const char *name, const char *macro, + const char *status) +{ + printf("%22s: ", name); + on_off_print(status); + printf(" # %s\n", macro); +} + +#define STATUS(__d, __m) \ +do { \ + if (IS_BUILTIN(__d)) \ + status_print(#__m, #__d, "on"); \ + else \ + status_print(#__m, #__d, "OFF"); \ +} while (0) + +static void library_status(void) +{ + STATUS(HAVE_DWARF_SUPPORT, dwarf); + STATUS(HAVE_DWARF_GETLOCATIONS_SUPPORT, dwarf_getlocations); + STATUS(HAVE_GLIBC_SUPPORT, glibc); + STATUS(HAVE_GTK2_SUPPORT, gtk2); + STATUS(HAVE_LIBAUDIT_SUPPORT, libaudit); + STATUS(HAVE_LIBBFD_SUPPORT, libbfd); + STATUS(HAVE_LIBELF_SUPPORT, libelf); + STATUS(HAVE_LIBNUMA_SUPPORT, libnuma); + STATUS(HAVE_LIBNUMA_SUPPORT, numa_num_possible_cpus); + STATUS(HAVE_LIBPERL_SUPPORT, libperl); + STATUS(HAVE_LIBPYTHON_SUPPORT, libpython); + STATUS(HAVE_SLANG_SUPPORT, libslang); + STATUS(HAVE_LIBCRYPTO_SUPPORT, libcrypto); + STATUS(HAVE_LIBUNWIND_SUPPORT, libunwind); + STATUS(HAVE_DWARF_SUPPORT, libdw-dwarf-unwind); + STATUS(HAVE_ZLIB_SUPPORT, zlib); + STATUS(HAVE_LZMA_SUPPORT, lzma); + STATUS(HAVE_AUXTRACE_SUPPORT, get_cpuid); + STATUS(HAVE_LIBBPF_SUPPORT, bpf); +} + +int cmd_version(int argc, const char **argv) +{ + argc = parse_options(argc, argv, version_options, version_usage, + PARSE_OPT_STOP_AT_NON_OPTION); + printf("perf version %s\n", perf_version_string); + + if (version.build_options || version_verbose == 1) + library_status(); + return 0; } From 3aa94b10ab0a818ed9fa2dc06c40812c136f9a5a Mon Sep 17 00:00:00 2001 From: Jin Yao Date: Fri, 30 Mar 2018 17:27:15 +0800 Subject: [PATCH 08/36] perf tools: Add 'perf -vv' as an alias to 'perf version --build-options' We keep having bug reports that when users build perf on their own, but they don't install some needed libraries such as libelf, libbfd/libibery. The perf can build, but it is missing important functionality. This patch provides a new option '-vv' for perf which will print the compiled-in status of libraries. The 'perf -vv' is mapped to 'perf version --build-options'. For example: $ ./perf -vv perf version 4.13.rc5.g6727c5 dwarf: [ on ] # HAVE_DWARF_SUPPORT dwarf_getlocations: [ on ] # HAVE_DWARF_GETLOCATIONS_SUPPORT glibc: [ on ] # HAVE_GLIBC_SUPPORT gtk2: [ on ] # HAVE_GTK2_SUPPORT libaudit: [ OFF ] # HAVE_LIBAUDIT_SUPPORT libbfd: [ on ] # HAVE_LIBBFD_SUPPORT libelf: [ on ] # HAVE_LIBELF_SUPPORT libnuma: [ on ] # HAVE_LIBNUMA_SUPPORT numa_num_possible_cpus: [ on ] # HAVE_LIBNUMA_SUPPORT libperl: [ on ] # HAVE_LIBPERL_SUPPORT libpython: [ on ] # HAVE_LIBPYTHON_SUPPORT libslang: [ on ] # HAVE_SLANG_SUPPORT libcrypto: [ on ] # HAVE_LIBCRYPTO_SUPPORT libunwind: [ on ] # HAVE_LIBUNWIND_SUPPORT libdw-dwarf-unwind: [ on ] # HAVE_DWARF_SUPPORT zlib: [ on ] # HAVE_ZLIB_SUPPORT lzma: [ on ] # HAVE_LZMA_SUPPORT get_cpuid: [ on ] # HAVE_AUXTRACE_SUPPORT bpf: [ on ] # HAVE_LIBBPF_SUPPORT v3: One bug is found in v2. It didn't process the option like '-vabc' correctly. Fix this bug. v2: Use a global variable version_verbose to record the number of 'v'. Signed-off-by: Jin Yao Tested-by: Arnaldo Carvalho de Melo Acked-by: Jiri Olsa Cc: Alexander Shishkin Cc: Andi Kleen Cc: Jin Yao Cc: Kan Liang Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1522402036-22915-6-git-send-email-yao.jin@linux.intel.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/perf.c | 6 ++++++ tools/perf/perf.h | 1 + 2 files changed, 7 insertions(+) diff --git a/tools/perf/perf.c b/tools/perf/perf.c index 1b3fc8ec0fa2..1659029d03fc 100644 --- a/tools/perf/perf.c +++ b/tools/perf/perf.c @@ -190,6 +190,12 @@ static int handle_options(const char ***argv, int *argc, int *envchanged) break; } + if (!strcmp(cmd, "-vv")) { + (*argv)[0] = "version"; + version_verbose = 1; + break; + } + /* * Check remaining flags. */ diff --git a/tools/perf/perf.h b/tools/perf/perf.h index 8fec1abd0f1f..a1a97956136f 100644 --- a/tools/perf/perf.h +++ b/tools/perf/perf.h @@ -84,6 +84,7 @@ struct record_opts { struct option; extern const char * const *record_usage; extern struct option *record_options; +extern int version_verbose; int record__parse_freq(const struct option *opt, const char *str, int unset); #endif From 709846725673a944ee38da1c275a6dfbf0576d0f Mon Sep 17 00:00:00 2001 From: Jin Yao Date: Fri, 30 Mar 2018 17:27:16 +0800 Subject: [PATCH 09/36] perf version: Add man page Since a new option '--build-options' is created for 'perf version', so we need to document it. Signed-off-by: Jin Yao Acked-by: Jiri Olsa Cc: Alexander Shishkin Cc: Andi Kleen Cc: Jin Yao Cc: Kan Liang Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1522402036-22915-7-git-send-email-yao.jin@linux.intel.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/Documentation/perf-version.txt | 24 +++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 tools/perf/Documentation/perf-version.txt diff --git a/tools/perf/Documentation/perf-version.txt b/tools/perf/Documentation/perf-version.txt new file mode 100644 index 000000000000..e207b7cfca26 --- /dev/null +++ b/tools/perf/Documentation/perf-version.txt @@ -0,0 +1,24 @@ +perf-version(1) +=============== + +NAME +---- +perf-version - display the version of perf binary + +SYNOPSIS +-------- +'perf version' [--build-options] + +DESCRIPTION +----------- +With no options given, the 'perf version' prints the perf version +on the standard output. + +If the option '--build-options' is given, then the status of +compiled-in libraries are printed on the standard output. + +OPTIONS +------- +--build-options:: + Prints the status of compiled-in libraries on the + standard output. From f016d24acd95660ca264e0424c8037391d165553 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 2 Apr 2018 14:00:04 -0300 Subject: [PATCH 10/36] perf hists browser: Rename perf_evsel_browser_title to a more descriptive name MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rename it to hists_browser__scnprintf_title() to better reflect that it provides a scnprintf-like function operating on a hists_browser instance. This paves the way to have a non-hists_browser specific function to scnprintf format a title with per evsel information to use in other tools or UIs. Cc: Adrian Hunter Cc: David Ahern Cc: Jiri Olsa Cc: Martin Liška Cc: Namhyung Kim Cc: Wang Nan Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=196935 Link: https://lkml.kernel.org/n/tip-sntpyzxsnme9jvuz2qntwoh2@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/ui/browsers/hists.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c index 8b4e82548f8e..2ac66011354f 100644 --- a/tools/perf/ui/browsers/hists.c +++ b/tools/perf/ui/browsers/hists.c @@ -32,8 +32,7 @@ extern void hist_browser__init_hpp(void); -static int perf_evsel_browser_title(struct hist_browser *browser, - char *bf, size_t size); +static int hists_browser__scnprintf_title(struct hist_browser *browser, char *bf, size_t size); static void hist_browser__update_nr_entries(struct hist_browser *hb); static struct rb_node *hists__filter_entries(struct rb_node *nd, @@ -2183,7 +2182,7 @@ perf_evsel_browser__new(struct perf_evsel *evsel, if (browser) { browser->hbt = hbt; browser->env = env; - browser->title = perf_evsel_browser_title; + browser->title = hists_browser__scnprintf_title; } return browser; } @@ -2209,8 +2208,7 @@ static inline bool is_report_browser(void *timer) return timer == NULL; } -static int perf_evsel_browser_title(struct hist_browser *browser, - char *bf, size_t size) +static int hists_browser__scnprintf_title(struct hist_browser *browser, char *bf, size_t size) { struct hist_browser_timer *hbt = browser->hbt; struct hists *hists = browser->hists; From 967a464a7e6d939f0b0dbb4ee41bd3d515fa9a6d Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 2 Apr 2018 14:20:20 -0300 Subject: [PATCH 11/36] perf hists: Introduce hists__scnprint_title() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit That is not use any struct hists_browser internals, so that it can be shared with the other UIs and tools. Cc: Adrian Hunter Cc: David Ahern Cc: Jiri Olsa Cc: Martin Liška Cc: Namhyung Kim Cc: Wang Nan Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=196935 Link: https://lkml.kernel.org/n/tip-w8mczjnqnbcj9yzfkv9ja6ro@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/ui/browsers/hists.c | 15 +++++++++++---- tools/perf/util/hist.h | 6 ++++++ 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c index 2ac66011354f..c20f0ad22f34 100644 --- a/tools/perf/ui/browsers/hists.c +++ b/tools/perf/ui/browsers/hists.c @@ -2208,10 +2208,8 @@ static inline bool is_report_browser(void *timer) return timer == NULL; } -static int hists_browser__scnprintf_title(struct hist_browser *browser, char *bf, size_t size) +int __hists__scnprintf_title(struct hists *hists, char *bf, size_t size, bool show_freq) { - struct hist_browser_timer *hbt = browser->hbt; - struct hists *hists = browser->hists; char unit; int printed; const struct dso *dso = hists->dso_filter; @@ -2254,7 +2252,7 @@ static int hists_browser__scnprintf_title(struct hist_browser *browser, char *bf strstr(ev_name, "call-graph=no")) enable_ref = true; - if (!is_report_browser(hbt)) + if (show_freq) scnprintf(sample_freq_str, sizeof(sample_freq_str), " %d Hz,", evsel->attr.sample_freq); nr_samples = convert_unit(nr_samples, &unit); @@ -2285,6 +2283,15 @@ static int hists_browser__scnprintf_title(struct hist_browser *browser, char *bf if (socket_id > -1) printed += scnprintf(bf + printed, size - printed, ", Processor Socket: %d", socket_id); + + return printed; +} + +static int hists_browser__scnprintf_title(struct hist_browser *browser, char *bf, size_t size) +{ + struct hist_browser_timer *hbt = browser->hbt; + int printed = __hists__scnprintf_title(browser->hists, bf, size, !is_report_browser(hbt)); + if (!is_report_browser(hbt)) { struct perf_top *top = hbt->arg; diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h index 32fbf26e0c18..fbabfd8a215d 100644 --- a/tools/perf/util/hist.h +++ b/tools/perf/util/hist.h @@ -504,5 +504,11 @@ int __hpp__slsmg_color_printf(struct perf_hpp *hpp, const char *fmt, ...); int __hist_entry__snprintf(struct hist_entry *he, struct perf_hpp *hpp, struct perf_hpp_list *hpp_list); int hists__fprintf_headers(struct hists *hists, FILE *fp); +int __hists__scnprintf_title(struct hists *hists, char *bf, size_t size, bool show_freq); + +static inline int hists__scnprintf_title(struct hists *hists, char *bf, size_t size) +{ + return __hists__scnprintf_title(hists, bf, size, true); +} #endif /* __PERF_HIST_H */ From 25c312dbf88ca402bf47389c5aa4f1552799a8ca Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 2 Apr 2018 14:24:28 -0300 Subject: [PATCH 12/36] perf hists: Move hists__scnprintf_title() away from the TUI code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The previous patch made this function useful to non-TUI parts of the tools, but left it where the function from what it was carved, so that the patch showed more clearly the process. Now just move it outside the TUI parts so that we can finally use it, even when the TUI code doesn't get built/linked. Cc: Adrian Hunter Cc: David Ahern Cc: Jiri Olsa Cc: Martin Liška Cc: Namhyung Kim Cc: Wang Nan Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=196935 Link: https://lkml.kernel.org/n/tip-hqj7hvcr3mu5lvcqp3cssio6@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/ui/browsers/hists.c | 79 --------------------------------- tools/perf/util/hist.c | 81 ++++++++++++++++++++++++++++++++++ 2 files changed, 81 insertions(+), 79 deletions(-) diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c index c20f0ad22f34..cde9bab5061d 100644 --- a/tools/perf/ui/browsers/hists.c +++ b/tools/perf/ui/browsers/hists.c @@ -2208,85 +2208,6 @@ static inline bool is_report_browser(void *timer) return timer == NULL; } -int __hists__scnprintf_title(struct hists *hists, char *bf, size_t size, bool show_freq) -{ - char unit; - int printed; - const struct dso *dso = hists->dso_filter; - const struct thread *thread = hists->thread_filter; - int socket_id = hists->socket_filter; - unsigned long nr_samples = hists->stats.nr_events[PERF_RECORD_SAMPLE]; - u64 nr_events = hists->stats.total_period; - struct perf_evsel *evsel = hists_to_evsel(hists); - const char *ev_name = perf_evsel__name(evsel); - char buf[512], sample_freq_str[64] = ""; - size_t buflen = sizeof(buf); - char ref[30] = " show reference callgraph, "; - bool enable_ref = false; - - if (symbol_conf.filter_relative) { - nr_samples = hists->stats.nr_non_filtered_samples; - nr_events = hists->stats.total_non_filtered_period; - } - - if (perf_evsel__is_group_event(evsel)) { - struct perf_evsel *pos; - - perf_evsel__group_desc(evsel, buf, buflen); - ev_name = buf; - - for_each_group_member(pos, evsel) { - struct hists *pos_hists = evsel__hists(pos); - - if (symbol_conf.filter_relative) { - nr_samples += pos_hists->stats.nr_non_filtered_samples; - nr_events += pos_hists->stats.total_non_filtered_period; - } else { - nr_samples += pos_hists->stats.nr_events[PERF_RECORD_SAMPLE]; - nr_events += pos_hists->stats.total_period; - } - } - } - - if (symbol_conf.show_ref_callgraph && - strstr(ev_name, "call-graph=no")) - enable_ref = true; - - if (show_freq) - scnprintf(sample_freq_str, sizeof(sample_freq_str), " %d Hz,", evsel->attr.sample_freq); - - nr_samples = convert_unit(nr_samples, &unit); - printed = scnprintf(bf, size, - "Samples: %lu%c of event%s '%s',%s%sEvent count (approx.): %" PRIu64, - nr_samples, unit, evsel->nr_members > 1 ? "s" : "", - ev_name, sample_freq_str, enable_ref ? ref : " ", nr_events); - - - if (hists->uid_filter_str) - printed += snprintf(bf + printed, size - printed, - ", UID: %s", hists->uid_filter_str); - if (thread) { - if (hists__has(hists, thread)) { - printed += scnprintf(bf + printed, size - printed, - ", Thread: %s(%d)", - (thread->comm_set ? thread__comm_str(thread) : ""), - thread->tid); - } else { - printed += scnprintf(bf + printed, size - printed, - ", Thread: %s", - (thread->comm_set ? thread__comm_str(thread) : "")); - } - } - if (dso) - printed += scnprintf(bf + printed, size - printed, - ", DSO: %s", dso->short_name); - if (socket_id > -1) - printed += scnprintf(bf + printed, size - printed, - ", Processor Socket: %d", socket_id); - - return printed; -} - static int hists_browser__scnprintf_title(struct hist_browser *browser, char *bf, size_t size) { struct hist_browser_timer *hbt = browser->hbt; diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c index 7d968892ee39..4d602fba40b2 100644 --- a/tools/perf/util/hist.c +++ b/tools/perf/util/hist.c @@ -6,6 +6,7 @@ #include "session.h" #include "namespaces.h" #include "sort.h" +#include "units.h" #include "evlist.h" #include "evsel.h" #include "annotate.h" @@ -14,6 +15,7 @@ #include "ui/progress.h" #include #include +#include #include static bool hists__filter_entry_by_dso(struct hists *hists, @@ -2454,6 +2456,85 @@ u64 hists__total_period(struct hists *hists) hists->stats.total_period; } +int __hists__scnprintf_title(struct hists *hists, char *bf, size_t size, bool show_freq) +{ + char unit; + int printed; + const struct dso *dso = hists->dso_filter; + const struct thread *thread = hists->thread_filter; + int socket_id = hists->socket_filter; + unsigned long nr_samples = hists->stats.nr_events[PERF_RECORD_SAMPLE]; + u64 nr_events = hists->stats.total_period; + struct perf_evsel *evsel = hists_to_evsel(hists); + const char *ev_name = perf_evsel__name(evsel); + char buf[512], sample_freq_str[64] = ""; + size_t buflen = sizeof(buf); + char ref[30] = " show reference callgraph, "; + bool enable_ref = false; + + if (symbol_conf.filter_relative) { + nr_samples = hists->stats.nr_non_filtered_samples; + nr_events = hists->stats.total_non_filtered_period; + } + + if (perf_evsel__is_group_event(evsel)) { + struct perf_evsel *pos; + + perf_evsel__group_desc(evsel, buf, buflen); + ev_name = buf; + + for_each_group_member(pos, evsel) { + struct hists *pos_hists = evsel__hists(pos); + + if (symbol_conf.filter_relative) { + nr_samples += pos_hists->stats.nr_non_filtered_samples; + nr_events += pos_hists->stats.total_non_filtered_period; + } else { + nr_samples += pos_hists->stats.nr_events[PERF_RECORD_SAMPLE]; + nr_events += pos_hists->stats.total_period; + } + } + } + + if (symbol_conf.show_ref_callgraph && + strstr(ev_name, "call-graph=no")) + enable_ref = true; + + if (show_freq) + scnprintf(sample_freq_str, sizeof(sample_freq_str), " %d Hz,", evsel->attr.sample_freq); + + nr_samples = convert_unit(nr_samples, &unit); + printed = scnprintf(bf, size, + "Samples: %lu%c of event%s '%s',%s%sEvent count (approx.): %" PRIu64, + nr_samples, unit, evsel->nr_members > 1 ? "s" : "", + ev_name, sample_freq_str, enable_ref ? ref : " ", nr_events); + + + if (hists->uid_filter_str) + printed += snprintf(bf + printed, size - printed, + ", UID: %s", hists->uid_filter_str); + if (thread) { + if (hists__has(hists, thread)) { + printed += scnprintf(bf + printed, size - printed, + ", Thread: %s(%d)", + (thread->comm_set ? thread__comm_str(thread) : ""), + thread->tid); + } else { + printed += scnprintf(bf + printed, size - printed, + ", Thread: %s", + (thread->comm_set ? thread__comm_str(thread) : "")); + } + } + if (dso) + printed += scnprintf(bf + printed, size - printed, + ", DSO: %s", dso->short_name); + if (socket_id > -1) + printed += scnprintf(bf + printed, size - printed, + ", Processor Socket: %d", socket_id); + + return printed; +} + int parse_filter_percentage(const struct option *opt __maybe_unused, const char *arg, int unset __maybe_unused) { From ef9ff6017e3c4593f3efa5776784cb417c58ad6c Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 2 Apr 2018 15:48:18 -0300 Subject: [PATCH 13/36] perf ui browser: Move the extra title lines from the hists browser MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This will be useful for the annotate browser as well, that wants to have extra title lines, i.e. the current ui_browser unconditionally reserves the first line for a browser title and the last one for status messages. But some browsers, like the buckets one (hists browser) needs extra lines to show headers, allowing it to be shown or not, press 'H' in 'perf top' or 'perf report' to see this feature. So move that logic to the core ui_browser used by the hists_browser ('perf top' and 'perf report' main interface) so that it can be used by the annotate browser too. Cc: Adrian Hunter Cc: David Ahern Cc: Jiri Olsa Cc: Martin Liška Cc: Namhyung Kim Cc: Wang Nan Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=196935 Link: https://lkml.kernel.org/n/tip-r38xm3ut37ulbg1o5tn5iise@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/ui/browser.c | 8 ++++++- tools/perf/ui/browser.h | 2 ++ tools/perf/ui/browsers/hists.c | 43 +++++++++++++++++++--------------- 3 files changed, 33 insertions(+), 20 deletions(-) diff --git a/tools/perf/ui/browser.c b/tools/perf/ui/browser.c index 9f6ce29b83b4..d7bb2591838e 100644 --- a/tools/perf/ui/browser.c +++ b/tools/perf/ui/browser.c @@ -45,11 +45,16 @@ void ui_browser__set_percent_color(struct ui_browser *browser, ui_browser__set_color(browser, color); } -void ui_browser__gotorc(struct ui_browser *browser, int y, int x) +void ui_browser__gotorc_title(struct ui_browser *browser, int y, int x) { SLsmg_gotorc(browser->y + y, browser->x + x); } +void ui_browser__gotorc(struct ui_browser *browser, int y, int x) +{ + SLsmg_gotorc(browser->y + y + browser->extra_title_lines, browser->x + x); +} + void ui_browser__write_nstring(struct ui_browser *browser __maybe_unused, const char *msg, unsigned int width) { @@ -191,6 +196,7 @@ void ui_browser__refresh_dimensions(struct ui_browser *browser) { browser->width = SLtt_Screen_Cols - 1; browser->height = browser->rows = SLtt_Screen_Rows - 2; + browser->rows -= browser->extra_title_lines; browser->y = 1; browser->x = 0; } diff --git a/tools/perf/ui/browser.h b/tools/perf/ui/browser.h index 70057178ee34..aa5932e1d62e 100644 --- a/tools/perf/ui/browser.h +++ b/tools/perf/ui/browser.h @@ -17,6 +17,7 @@ struct ui_browser { u64 index, top_idx; void *top, *entries; u16 y, x, width, height, rows, columns, horiz_scroll; + u8 extra_title_lines; int current_color; void *priv; const char *title; @@ -38,6 +39,7 @@ bool ui_browser__is_current_entry(struct ui_browser *browser, unsigned row); void ui_browser__refresh_dimensions(struct ui_browser *browser); void ui_browser__reset_index(struct ui_browser *browser); +void ui_browser__gotorc_title(struct ui_browser *browser, int y, int x); void ui_browser__gotorc(struct ui_browser *browser, int y, int x); void ui_browser__write_nstring(struct ui_browser *browser, const char *msg, unsigned int width); diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c index cde9bab5061d..b06afb8f51fb 100644 --- a/tools/perf/ui/browsers/hists.c +++ b/tools/perf/ui/browsers/hists.c @@ -61,6 +61,15 @@ static int hist_browser__get_folding(struct hist_browser *browser) return unfolded_rows; } +static void hist_browser__set_title_space(struct hist_browser *hb) +{ + struct ui_browser *browser = &hb->b; + struct hists *hists = hb->hists; + struct perf_hpp_list *hpp_list = hists->hpp_list; + + browser->extra_title_lines = hb->show_headers ? hpp_list->nr_header_lines : 0; +} + static u32 hist_browser__nr_entries(struct hist_browser *hb) { u32 nr_entries; @@ -81,10 +90,16 @@ static void hist_browser__update_rows(struct hist_browser *hb) struct ui_browser *browser = &hb->b; struct hists *hists = hb->hists; struct perf_hpp_list *hpp_list = hists->hpp_list; - u16 header_offset, index_row; + u16 index_row; - header_offset = hb->show_headers ? hpp_list->nr_header_lines : 0; - browser->rows = browser->height - header_offset; + if (!hb->show_headers) { + browser->rows += browser->extra_title_lines; + browser->extra_title_lines = 0; + return; + } + + browser->extra_title_lines = hpp_list->nr_header_lines; + browser->rows -= browser->extra_title_lines; /* * Verify if we were at the last line and that line isn't * visibe because we now show the header line(s). @@ -107,17 +122,6 @@ static void hist_browser__refresh_dimensions(struct ui_browser *browser) * changeset. */ ui_browser__refresh_dimensions(browser); - hist_browser__update_rows(hb); -} - -static void hist_browser__gotorc(struct hist_browser *browser, int row, int column) -{ - struct hists *hists = browser->hists; - struct perf_hpp_list *hpp_list = hists->hpp_list; - u16 header_offset; - - header_offset = browser->show_headers ? hpp_list->nr_header_lines : 0; - ui_browser__gotorc(&browser->b, row + header_offset, column); } static void hist_browser__reset(struct hist_browser *browser) @@ -732,7 +736,7 @@ static void hist_browser__show_callchain_entry(struct hist_browser *browser, } ui_browser__set_color(&browser->b, color); - hist_browser__gotorc(browser, row, 0); + ui_browser__gotorc(&browser->b, row, 0); ui_browser__write_nstring(&browser->b, " ", offset); ui_browser__printf(&browser->b, "%c", folded_sign); ui_browser__write_graph(&browser->b, show_annotated ? SLSMG_RARROW_CHAR : ' '); @@ -1248,7 +1252,7 @@ static int hist_browser__show_entry(struct hist_browser *browser, }; int column = 0; - hist_browser__gotorc(browser, row, 0); + ui_browser__gotorc(&browser->b, row, 0); hists__for_each_format(browser->hists, fmt) { char s[2048]; @@ -1357,7 +1361,7 @@ static int hist_browser__show_hierarchy_entry(struct hist_browser *browser, goto show_callchain; } - hist_browser__gotorc(browser, row, 0); + ui_browser__gotorc(&browser->b, row, 0); if (current_entry && browser->b.navkeypressed) ui_browser__set_color(&browser->b, HE_COLORSET_SELECTED); @@ -1506,7 +1510,7 @@ static int hist_browser__show_no_entry(struct hist_browser *browser, browser->selection = NULL; } - hist_browser__gotorc(browser, row, 0); + ui_browser__gotorc(&browser->b, row, 0); if (current_entry && browser->b.navkeypressed) ui_browser__set_color(&browser->b, HE_COLORSET_SELECTED); @@ -1712,7 +1716,7 @@ static void hists_browser__headers(struct hist_browser *browser) hists_browser__scnprintf_headers(browser, headers, sizeof(headers), line); - ui_browser__gotorc(&browser->b, line, 0); + ui_browser__gotorc_title(&browser->b, line, 0); ui_browser__set_color(&browser->b, HE_COLORSET_ROOT); ui_browser__write_nstring(&browser->b, headers, browser->b.width + 1); } @@ -2142,6 +2146,7 @@ void hist_browser__init(struct hist_browser *browser, browser->b.seek = ui_browser__hists_seek; browser->b.use_navkeypressed = true; browser->show_headers = symbol_conf.show_hist_headers; + hist_browser__set_title_space(browser); if (symbol_conf.report_hierarchy) { struct perf_hpp_list_node *fmt_node; From b213eac245aa2d29a3b9dd90f3b96ab182337ee8 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 3 Apr 2018 15:19:47 -0300 Subject: [PATCH 14/36] perf annotate: Introduce annotation__scnprintf_samples_period() method MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit To print a string using the total period (nr_events) and the number of samples for a given annotation, i.e. for a given symbol, the counterpart to hists__scnprintf_samples_period(), that is for all the samples in a session (be it a live session, think 'perf top' or a perf.data file, think 'perf report'). Cc: Adrian Hunter Cc: David Ahern Cc: Jiri Olsa Cc: Martin Liška Cc: Namhyung Kim Cc: Wang Nan Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=196935 Link: https://lkml.kernel.org/n/tip-goj2wu4fxutc8vd46mw3yg14@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/annotate.c | 38 ++++++++++++++++++++++++++++++++++++++ tools/perf/util/annotate.h | 12 ++++++++++++ 2 files changed, 50 insertions(+) diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c index 3a428d7c59b9..b956bb7eabcf 100644 --- a/tools/perf/util/annotate.c +++ b/tools/perf/util/annotate.c @@ -17,6 +17,7 @@ #include "config.h" #include "cache.h" #include "symbol.h" +#include "units.h" #include "debug.h" #include "annotate.h" #include "evsel.h" @@ -2597,6 +2598,43 @@ out_free_offsets: return -1; } +int __annotation__scnprintf_samples_period(struct annotation *notes, + char *bf, size_t size, + struct perf_evsel *evsel, + bool show_freq) +{ + const char *ev_name = perf_evsel__name(evsel); + char ref[30] = " show reference callgraph, "; + char sample_freq_str[64] = ""; + unsigned long nr_samples = 0; + int nr_members = 1; + bool enable_ref = false; + u64 nr_events = 0; + char unit; + int i; + + if (perf_evsel__is_group_event(evsel)) + nr_members = evsel->nr_members; + + for (i = 0; i < nr_members; i++) { + struct sym_hist *ah = annotation__histogram(notes, evsel->idx + i); + + nr_samples += ah->nr_samples; + nr_events += ah->period; + } + + if (symbol_conf.show_ref_callgraph && strstr(ev_name, "call-graph=no")) + enable_ref = true; + + if (show_freq) + scnprintf(sample_freq_str, sizeof(sample_freq_str), " %d Hz,", evsel->attr.sample_freq); + + nr_samples = convert_unit(nr_samples, &unit); + return scnprintf(bf, size, "Samples: %lu%c of event%s '%s',%s%sEvent count (approx.): %" PRIu64, + nr_samples, unit, evsel->nr_members > 1 ? "s" : "", + ev_name, sample_freq_str, enable_ref ? ref : " ", nr_events); +} + #define ANNOTATION__CFG(n) \ { .name = #n, .value = &annotation__default_options.n, } diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h index ff7e3df31efa..db8d09bea07e 100644 --- a/tools/perf/util/annotate.h +++ b/tools/perf/util/annotate.h @@ -151,6 +151,18 @@ double annotation_line__max_percent(struct annotation_line *al, struct annotatio void annotation_line__write(struct annotation_line *al, struct annotation *notes, struct annotation_write_ops *ops); +int __annotation__scnprintf_samples_period(struct annotation *notes, + char *bf, size_t size, + struct perf_evsel *evsel, + bool show_freq); + +static inline int annotation__scnprintf_samples_period(struct annotation *notes, + char *bf, size_t size, + struct perf_evsel *evsel) +{ + return __annotation__scnprintf_samples_period(notes, bf, size, evsel, true); +} + int disasm_line__scnprintf(struct disasm_line *dl, char *bf, size_t size, bool raw); size_t disasm__fprintf(struct list_head *head, FILE *fp); void symbol__calc_percent(struct symbol *sym, struct perf_evsel *evsel); From 6920e2854e9a16226ca57199d48fd6b68819f6d5 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 2 Apr 2018 16:18:45 -0300 Subject: [PATCH 15/36] perf annotate browser: Show extra title line with event information MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit So at the top we'll have two lines, like this, from 'perf report': # perf report --group --ignore-vmlinux ===================================================================================================== Samples: 46 of events 'cycles', 4000 Hz, Event count (approx.): 5154895 _raw_spin_lock_irqsave /proc/kcore Percent │ nop │ push %rbx 0.00 14.29 0.00 │ pushfq 9.09 0.00 0.00 │ pop %rax 9.09 0.00 20.00 │ nop │ mov %rax,%rbx │ cli 4.55 7.14 0.00 │ nop │ xor %eax,%eax │ mov $0x1,%edx │ lock cmpxchg %edx,(%rdi) 77.27 78.57 70.00 │ test %eax,%eax │ ↓ jne 2b │ mov %rbx,%rax 0.00 0.00 10.00 │ pop %rbx │ ← retq │2b: mov %eax,%esi │ → callq queued_spin_lock_slowpath │ mov %rbx,%rax │ pop %rbx Press 'h' for help on│key bindings ===================================================================================================== 9.09 + 9.09 + 4.55 + 77.27 = 100 14.29 + 7.14 + 78.57 = 100 20 + 70 + 10 = 100 We can do the math by using 't' to toggle from 'percent' to nr ===================================================================================================== Samples: 46 of events 'cycles', 4000 Hz, Event count (approx.): 5154895 _raw_spin_lock_irqsave /proc/kcore Period │ nop │ push %rbx 0 79273 0 │ pushfq 190455 0 0 │ pop %rax 198038 0 3045 │ nop │ mov %rax,%rbx │ cli 217233 32562 0 │ nop │ xor %eax,%eax │ mov $0x1,%edx │ lock cmpxchg %edx,(%rdi) 3421649 979174 28273 │ test %eax,%eax │ ↓ jne 2b │ mov %rbx,%rax 0 0 5193 │ pop %rbx │ ← retq │2b: mov %eax,%esi │ → callq queued_spin_lock_slowpath │ mov %rbx,%rax │ pop %rbx Press 'h' for help on│key bindings ===================================================================================================== 79273 + 190455 + 198038 + 3045 + 217233 + 32562 + 3421649 + 979174 + 28273 + 5193 = 5154895 Or number of samples: ===================================================================================================== ooSamples: 46 of events 'cycles', 4000 Hz, Event count (approx.): 5154895 _raw_spin_lock_irqsave /proc/kcore Samples │ nop │ push %rbx 0 2 0 │ pushfq 2 0 0 │ pop %rax 2 0 2 │ nop │ mov %rax,%rbx │ cli 1 1 0 │ nop │ xor %eax,%eax │ mov $0x1,%edx │ lock cmpxchg %edx,(%rdi) 17 11 7 │ test %eax,%eax │ ↓ jne 2b │ mov %rbx,%rax 0 0 1 │ pop %rbx │ ← retq │2b: mov %eax,%esi │ → callq queued_spin_lock_slowpath │ mov %rbx,%rax │ pop %rbx Press 'h' for help on key bindings ===================================================================================================== 2 + 2 + 2 + 2 + 1 + 1 + 17 + 11 + 7 + 1 = 46 Suggested-by: Martin Liška Cc: Adrian Hunter Cc: David Ahern Cc: Jiri Olsa Cc: Linus Torvalds Cc: Namhyung Kim Cc: Wang Nan Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=196935 Link: https://lkml.kernel.org/n/tip-ezccyxld50wtwyt66np6aomo@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/ui/browsers/annotate.c | 31 +++++++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/tools/perf/ui/browsers/annotate.c b/tools/perf/ui/browsers/annotate.c index c02fb437ac8e..78bcd220f1b6 100644 --- a/tools/perf/ui/browsers/annotate.c +++ b/tools/perf/ui/browsers/annotate.c @@ -592,21 +592,40 @@ bool annotate_browser__continue_search_reverse(struct annotate_browser *browser, return __annotate_browser__search_reverse(browser); } +static int annotate_browser__show(struct ui_browser *browser, char *title, const char *help) +{ + struct map_symbol *ms = browser->priv; + struct symbol *sym = ms->sym; + char symbol_dso[SYM_TITLE_MAX_SIZE]; + + if (ui_browser__show(browser, title, help) < 0) + return -1; + + sym_title(sym, ms->map, symbol_dso, sizeof(symbol_dso)); + + ui_browser__gotorc_title(browser, 0, 0); + ui_browser__set_color(browser, HE_COLORSET_ROOT); + ui_browser__write_nstring(browser, symbol_dso, browser->width + 1); + return 0; +} + static int annotate_browser__run(struct annotate_browser *browser, struct perf_evsel *evsel, struct hist_browser_timer *hbt) { struct rb_node *nd = NULL; + struct hists *hists = evsel__hists(evsel); struct map_symbol *ms = browser->b.priv; struct symbol *sym = ms->sym; struct annotation *notes = symbol__annotation(ms->sym); const char *help = "Press 'h' for help on key bindings"; int delay_secs = hbt ? hbt->refresh : 0; + char title[256]; int key; - char title[SYM_TITLE_MAX_SIZE]; - sym_title(sym, ms->map, title, sizeof(title)); - if (ui_browser__show(&browser->b, title, help) < 0) + annotation__scnprintf_samples_period(notes, title, sizeof(title), evsel); + + if (annotate_browser__show(&browser->b, title, help) < 0) return -1; annotate_browser__calc_percent(browser, evsel); @@ -637,8 +656,11 @@ static int annotate_browser__run(struct annotate_browser *browser, if (hbt) hbt->timer(hbt->arg); - if (delay_secs != 0) + if (delay_secs != 0) { symbol__annotate_decay_histogram(sym, evsel->idx); + hists__scnprintf_title(hists, title, sizeof(title)); + annotate_browser__show(&browser->b, title, help); + } continue; case K_TAB: if (nd != NULL) { @@ -812,6 +834,7 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map, .seek = ui_browser__list_head_seek, .write = annotate_browser__write, .filter = disasm_line__filter, + .extra_title_lines = 1, /* for hists__scnprintf_title() */ .priv = &ms, .use_navkeypressed = true, }, From 520d3f01ea5322edeedff4bb25a0aff07ad72d43 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 2 Apr 2018 16:42:01 -0300 Subject: [PATCH 16/36] perf annotate stdio2: Print more descriptive event information header MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit To match the recently added event header information to --tui, e.g.: # perf annotate --ignore-vmlinux --stdio2 _raw_spin_lock_irqsave Samples: 128 of event 'cycles:ppp', 4000 Hz, Event count (approx.): 48617682 _raw_spin_lock_irqsave() /proc/kcore 0.78 nop 7.03 push %rbx 3.12 pushfq 6.25 pop %rax nop mov %rax,%rbx 3.12 cli nop xor %eax,%eax mov $0x1,%edx 79.69 lock cmpxchg %edx,(%rdi) test %eax,%eax ↓ jne 2b mov %rbx,%rax pop %rbx ← retq 2b: mov %eax,%esi → callq *ffffffffb30eaed0 mov %rbx,%rax pop %rbx ← retq # Cc: Adrian Hunter Cc: David Ahern Cc: Jiri Olsa Cc: Martin Liška Cc: Namhyung Kim Cc: Wang Nan Link: https://lkml.kernel.org/n/tip-ujy46x7cldyhyxelyf2b9quy@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/annotate.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c index b956bb7eabcf..fffe16af9797 100644 --- a/tools/perf/util/annotate.c +++ b/tools/perf/util/annotate.c @@ -2325,7 +2325,7 @@ int symbol__tty_annotate2(struct symbol *sym, struct map *map, struct dso *dso = map->dso; struct rb_root source_line = RB_ROOT; struct annotation_options opts = annotation__default_options; - const char *ev_name = perf_evsel__name(evsel); + struct annotation *notes = symbol__annotation(sym); char buf[1024]; if (symbol__annotate2(sym, map, evsel, &opts, NULL) < 0) @@ -2337,12 +2337,8 @@ int symbol__tty_annotate2(struct symbol *sym, struct map *map, print_summary(&source_line, dso->long_name); } - if (perf_evsel__is_group_event(evsel)) { - perf_evsel__group_desc(evsel, buf, sizeof(buf)); - ev_name = buf; - } - - fprintf(stdout, "%s() %s\nEvent: %s\n\n", sym->name, dso->long_name, ev_name); + annotation__scnprintf_samples_period(notes, buf, sizeof(buf), evsel); + fprintf(stdout, "%s\n%s() %s\n", buf, sym->name, dso->long_name); symbol__annotate_fprintf2(sym, stdout); annotated_source__purge(symbol__annotation(sym)->src); From 51125a29a395048fdb3429b8c4ca0ada57097744 Mon Sep 17 00:00:00 2001 From: Changbin Du Date: Tue, 13 Mar 2018 18:40:01 +0800 Subject: [PATCH 17/36] perf trace: Remove redundant ')' There is a redundant ')' at the tail of each event. So remove it. $ sudo perf trace --no-syscalls -e 'kmem:*' -a 899.342 kmem:kfree:(vfs_writev+0xb9) call_site=ffffffff9c453979 ptr=(nil)) 899.344 kmem:kfree:(___sys_recvmsg+0x188) call_site=ffffffff9c9b8b88 ptr=(nil)) Signed-off-by: Changbin Du Tested-by: Arnaldo Carvalho de Melo Cc: Jiri Olsa Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1520937601-24952-1-git-send-email-changbin.du@intel.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-trace.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 4e03f0f68241..3ad17ee89403 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -1962,7 +1962,7 @@ static int trace__event_handler(struct trace *trace, struct perf_evsel *evsel, trace->output); } - fprintf(trace->output, ")\n"); + fprintf(trace->output, "\n"); if (callchain_ret > 0) trace__fprintf_callchain(trace, sample); From d1e7e602cd64cf61f87dbf30df07c24df9eb1d99 Mon Sep 17 00:00:00 2001 From: Stephane Eranian Date: Wed, 4 Apr 2018 23:29:51 -0700 Subject: [PATCH 18/36] perf/x86/intel: Move regs->flags EXACT bit init This patch removes a redundant store on regs->flags introduced by commit: 71eb9ee9596d ("perf/x86/intel: Fix linear IP of PEBS real_ip on Haswell and later CPUs") We were clearing the PERF_EFLAGS_EXACT but it was overwritten by regs->flags = pebs->flags later on. The PERF_EFLAGS_EXACT is a software flag using bit 3 of regs->flags. X86 marks this bit as Reserved. To make sure this bit is zero before we do any IP processing, we clear it explicitly. Patch also removes the following assignment: regs->flags = pebs->flags | (regs->flags & PERF_EFLAGS_VM); Because there is no regs->flags to preserve anymore because set_linear_ip() is not called until later. Signed-off-by: Stephane Eranian Cc: Alexander Shishkin Cc: Arnaldo Carvalho de Melo Cc: Jiri Olsa Cc: Linus Torvalds Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: Vince Weaver Cc: kan.liang@intel.com Link: http://lkml.kernel.org/r/1522909791-32498-1-git-send-email-eranian@google.com [ Improve capitalization, punctuation and clarity of comments. ] Signed-off-by: Ingo Molnar --- arch/x86/events/intel/ds.c | 34 ++++++++++++++++++++++++---------- 1 file changed, 24 insertions(+), 10 deletions(-) diff --git a/arch/x86/events/intel/ds.c b/arch/x86/events/intel/ds.c index da6780122786..8a10a045b57b 100644 --- a/arch/x86/events/intel/ds.c +++ b/arch/x86/events/intel/ds.c @@ -1153,7 +1153,6 @@ static void setup_pebs_sample_data(struct perf_event *event, if (pebs == NULL) return; - regs->flags &= ~PERF_EFLAGS_EXACT; sample_type = event->attr.sample_type; dsrc = sample_type & PERF_SAMPLE_DATA_SRC; @@ -1197,7 +1196,13 @@ static void setup_pebs_sample_data(struct perf_event *event, * and PMI. */ *regs = *iregs; - regs->flags = pebs->flags; + + /* + * Initialize regs_>flags from PEBS, + * Clear exact bit (which uses x86 EFLAGS Reserved bit 3), + * i.e., do not rely on it being zero: + */ + regs->flags = pebs->flags & ~PERF_EFLAGS_EXACT; if (sample_type & PERF_SAMPLE_REGS_INTR) { regs->ax = pebs->ax; @@ -1217,10 +1222,6 @@ static void setup_pebs_sample_data(struct perf_event *event, regs->sp = pebs->sp; } - /* - * Preserve PERF_EFLAGS_VM from set_linear_ip(). - */ - regs->flags = pebs->flags | (regs->flags & PERF_EFLAGS_VM); #ifndef CONFIG_X86_32 regs->r8 = pebs->r8; regs->r9 = pebs->r9; @@ -1234,20 +1235,33 @@ static void setup_pebs_sample_data(struct perf_event *event, } if (event->attr.precise_ip > 1) { - /* Haswell and later have the eventing IP, so use it: */ + /* + * Haswell and later processors have an 'eventing IP' + * (real IP) which fixes the off-by-1 skid in hardware. + * Use it when precise_ip >= 2 : + */ if (x86_pmu.intel_cap.pebs_format >= 2) { set_linear_ip(regs, pebs->real_ip); regs->flags |= PERF_EFLAGS_EXACT; } else { - /* Otherwise use PEBS off-by-1 IP: */ + /* Otherwise, use PEBS off-by-1 IP: */ set_linear_ip(regs, pebs->ip); - /* ... and try to fix it up using the LBR entries: */ + /* + * With precise_ip >= 2, try to fix up the off-by-1 IP + * using the LBR. If successful, the fixup function + * corrects regs->ip and calls set_linear_ip() on regs: + */ if (intel_pmu_pebs_fixup_ip(regs)) regs->flags |= PERF_EFLAGS_EXACT; } - } else + } else { + /* + * When precise_ip == 1, return the PEBS off-by-1 IP, + * no fixup attempted: + */ set_linear_ip(regs, pebs->ip); + } if ((sample_type & (PERF_SAMPLE_ADDR | PERF_SAMPLE_PHYS_ADDR)) && From 0d75f123a6dcdacb3550b0c3c44a283f7259289e Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Tue, 6 Mar 2018 11:13:17 +0200 Subject: [PATCH 19/36] perf auxtrace: Make auxtrace_queues__add_buffer() allocate struct buffer In preparation for supporting AUX area sampling buffers, auxtrace_queues__add_buffer() needs to be more generic. To that end, move memory allocation for struct buffer into it. Signed-off-by: Adrian Hunter Cc: Jiri Olsa Link: http://lkml.kernel.org/r/1520327598-1317-7-git-send-email-adrian.hunter@intel.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/auxtrace.c | 54 +++++++++++++++++--------------------- 1 file changed, 24 insertions(+), 30 deletions(-) diff --git a/tools/perf/util/auxtrace.c b/tools/perf/util/auxtrace.c index fb357a00dd86..e1aff91c54a8 100644 --- a/tools/perf/util/auxtrace.c +++ b/tools/perf/util/auxtrace.c @@ -308,7 +308,11 @@ static int auxtrace_queues__add_buffer(struct auxtrace_queues *queues, struct auxtrace_buffer *buffer, struct auxtrace_buffer **buffer_ptr) { - int err; + int err = -ENOMEM; + + buffer = memdup(buffer, sizeof(*buffer)); + if (!buffer) + return -ENOMEM; if (session->one_mmap) { buffer->data = buffer->data_offset - session->one_mmap_offset + @@ -316,24 +320,28 @@ static int auxtrace_queues__add_buffer(struct auxtrace_queues *queues, } else if (perf_data__is_pipe(session->data)) { buffer->data = auxtrace_copy_data(buffer->size, session); if (!buffer->data) - return -ENOMEM; + goto out_free; buffer->data_needs_freeing = true; } else if (BITS_PER_LONG == 32 && buffer->size > BUFFER_LIMIT_FOR_32_BIT) { err = auxtrace_queues__split_buffer(queues, idx, buffer); if (err) - return err; + goto out_free; } err = auxtrace_queues__queue_buffer(queues, idx, buffer); if (err) - return err; + goto out_free; /* FIXME: Doesn't work for split buffer */ if (buffer_ptr) *buffer_ptr = buffer; return 0; + +out_free: + auxtrace_buffer__free(buffer); + return err; } static bool filter_cpu(struct perf_session *session, int cpu) @@ -348,36 +356,22 @@ int auxtrace_queues__add_event(struct auxtrace_queues *queues, union perf_event *event, off_t data_offset, struct auxtrace_buffer **buffer_ptr) { - struct auxtrace_buffer *buffer; - unsigned int idx; - int err; + struct auxtrace_buffer buffer = { + .pid = -1, + .tid = event->auxtrace.tid, + .cpu = event->auxtrace.cpu, + .data_offset = data_offset, + .offset = event->auxtrace.offset, + .reference = event->auxtrace.reference, + .size = event->auxtrace.size, + }; + unsigned int idx = event->auxtrace.idx; if (filter_cpu(session, event->auxtrace.cpu)) return 0; - buffer = zalloc(sizeof(struct auxtrace_buffer)); - if (!buffer) - return -ENOMEM; - - buffer->pid = -1; - buffer->tid = event->auxtrace.tid; - buffer->cpu = event->auxtrace.cpu; - buffer->data_offset = data_offset; - buffer->offset = event->auxtrace.offset; - buffer->reference = event->auxtrace.reference; - buffer->size = event->auxtrace.size; - idx = event->auxtrace.idx; - - err = auxtrace_queues__add_buffer(queues, session, idx, buffer, - buffer_ptr); - if (err) - goto out_err; - - return 0; - -out_err: - auxtrace_buffer__free(buffer); - return err; + return auxtrace_queues__add_buffer(queues, session, idx, &buffer, + buffer_ptr); } static int auxtrace_queues__add_indexed_event(struct auxtrace_queues *queues, From c0459a092509f9c2ff91cc070cd2645d38e7cf7b Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Thu, 5 Apr 2018 11:13:24 -0300 Subject: [PATCH 20/36] perf annotate: Show group details on the title line MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit To match what is shown in the main 'perf report/top' title lines, i.e. if a group is being shown, either a real group (recorded with "-e '{a,b,c}') or a forced group (using 'perf report --group' for a perf.data file recorded without {}) we will show multiple columns, one per event, but we were failing to show the group details, so, for: # perf report --header-only | grep cmdline # cmdline : /home/acme/bin/perf record -e {cycles,instructions,cache-misses} # perf report --group The first line was showing just "cycles", now it shows the correct line, which is: Samples: 578 of events 'anon group { cycles, instructions, cache-misses }', 4000 Hz, Event count (approx.): 487421794 syscall_return_via_sysret /lib/modules/4.16.0-rc7/build/vmlinux 0.22 2.97 0.00 │ ↓ jmp 6c │ mov %cr3,%rdi 1.33 10.89 4.00 │ ↓ jmp 62 │ mov %rdi,%rax Cc: Adrian Hunter Cc: Andi Kleen Cc: David Ahern Cc: Jin Yao Cc: Jiri Olsa Cc: Namhyung Kim Cc: Wang Nan Fixes: 6920e2854e9a ("perf annotate browser: Show extra title line with event information") Link: https://lkml.kernel.org/n/tip-i41tqh17c2dabnyzjh99r1oz@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/annotate.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c index fffe16af9797..fbad8dfbb186 100644 --- a/tools/perf/util/annotate.c +++ b/tools/perf/util/annotate.c @@ -2600,7 +2600,7 @@ int __annotation__scnprintf_samples_period(struct annotation *notes, bool show_freq) { const char *ev_name = perf_evsel__name(evsel); - char ref[30] = " show reference callgraph, "; + char buf[1024], ref[30] = " show reference callgraph, "; char sample_freq_str[64] = ""; unsigned long nr_samples = 0; int nr_members = 1; @@ -2609,8 +2609,11 @@ int __annotation__scnprintf_samples_period(struct annotation *notes, char unit; int i; - if (perf_evsel__is_group_event(evsel)) + if (perf_evsel__is_group_event(evsel)) { + perf_evsel__group_desc(evsel, buf, sizeof(buf)); + ev_name = buf; nr_members = evsel->nr_members; + } for (i = 0; i < nr_members; i++) { struct sym_hist *ah = annotation__histogram(notes, evsel->idx + i); From e726c8511c052ba40dc943517b54011e42c2dfa3 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Thu, 5 Apr 2018 11:35:32 -0300 Subject: [PATCH 21/36] perf annotate browser: Fixup vertical line separating metrics from instructions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now that we can have extra title lines we should use ui_browser->rows and not ->height when drawing lines, as it will use ui_browser__gotorc() and that will take the extra title lines into account, which was causing an off by one at the end of the vertical line drawn by __ui_browser__vline(), fix it. The visual effect was that the last line, with status messages, was being overwritten by the vertical line, looking like: Press 'h' for help on│key bindings Cc: Adrian Hunter Cc: Andi Kleen Cc: David Ahern Cc: Jin Yao Cc: Jiri Olsa Cc: Namhyung Kim Cc: Wang Nan Fixes: ef9ff6017e3c ("perf ui browser: Move the extra title lines from the hists browser") Link: https://lkml.kernel.org/n/tip-08y1ln3xjn76zvizz1i1dsvn@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/ui/browsers/annotate.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/perf/ui/browsers/annotate.c b/tools/perf/ui/browsers/annotate.c index 78bcd220f1b6..12c099a87f8b 100644 --- a/tools/perf/ui/browsers/annotate.c +++ b/tools/perf/ui/browsers/annotate.c @@ -218,7 +218,7 @@ static unsigned int annotate_browser__refresh(struct ui_browser *browser) annotate_browser__draw_current_jump(browser); ui_browser__set_color(browser, HE_COLORSET_NORMAL); - __ui_browser__vline(browser, pcnt_width, 0, browser->height - 1); + __ui_browser__vline(browser, pcnt_width, 0, browser->rows - 1); return ret; } From caf61de356189f0925b23c3922bd16b53bb7c768 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Thu, 5 Apr 2018 11:43:38 -0300 Subject: [PATCH 22/36] perf ui browser: Fixup cleaning unused lines at the bottom Now that we can have extra title lines we should use ui_browser->rows and not ->height when drawing lines, as well as adding ui_browser->extra_title_lines to browser->y when cleaning unused lines at the bottom, otherwise we end up clobbering with spaces the last line just shown by ui_browser->refresh() routine. Cc: Adrian Hunter Cc: Andi Kleen Cc: David Ahern Cc: Jin Yao Cc: Jiri Olsa Cc: Namhyung Kim Cc: Wang Nan Fixes: ef9ff6017e3c ("perf ui browser: Move the extra title lines from the hists browser") Link: https://lkml.kernel.org/n/tip-dfcpokt1pm5ixm8n9pxwtstz@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/ui/browser.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/perf/ui/browser.c b/tools/perf/ui/browser.c index d7bb2591838e..4f75561424ed 100644 --- a/tools/perf/ui/browser.c +++ b/tools/perf/ui/browser.c @@ -343,8 +343,8 @@ static int __ui_browser__refresh(struct ui_browser *browser) else width += 1; - SLsmg_fill_region(browser->y + row, browser->x, - browser->height - row, width, ' '); + SLsmg_fill_region(browser->y + row + browser->extra_title_lines, browser->x, + browser->rows - row, width, ' '); return 0; } From 41a43dacecdbc9aec9d307bd9f6aa5ec16d65832 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Thu, 5 Apr 2018 14:34:09 -0300 Subject: [PATCH 23/36] perf report: Remove duplicated 'samples' in lost samples warning The following message, emitted when samples are lost due to system overload, had one 'samples' too many, ditch it: Processed 25333 samples and lost 20.88% samples! Cc: Adrian Hunter Cc: David Ahern Cc: Jiri Olsa Cc: Namhyung Kim Cc: Wang Nan Cc: Kan Liang Link: https://lkml.kernel.org/n/tip-oev1469y02hmfere6r2kkxp6@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/session.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index c71ced7db152..f4a7a437ee87 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -1591,7 +1591,7 @@ static void perf_session__warn_about_errors(const struct perf_session *session) drop_rate = (double)stats->total_lost_samples / (double) (stats->nr_events[PERF_RECORD_SAMPLE] + stats->total_lost_samples); if (drop_rate > 0.05) { - ui__warning("Processed %" PRIu64 " samples and lost %3.2f%% samples!\n\n", + ui__warning("Processed %" PRIu64 " samples and lost %3.2f%%!\n\n", stats->nr_events[PERF_RECORD_SAMPLE] + stats->total_lost_samples, drop_rate * 100.0); } From 01f97511f13cbf2ba3d23b2bffa06258dc81e283 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Thu, 5 Apr 2018 14:40:44 -0300 Subject: [PATCH 24/36] tools headers uapi: Synchronize i915_drm.h To pick up the changes in: c822e0591855 drm/i915: expose rcs topology through query uAPI a446ae2c6e65 drm/i915: add query uAPI This affects 'perf trace', that automagically gets the definition of the new I915_QUERY DRM ioctl: --- /tmp/build/perf/trace/beauty/generated/ioctl/drm_ioctl_array.c.old 2018-04-05 14:38:33.660111995 -0300 +++ /tmp/build/perf/trace/beauty/generated/ioctl/drm_ioctl_array.c 2018-04-05 14:40:17.923283914 -0300 @@ -158,4 +158,5 @@ [DRM_COMMAND_BASE + 0x36] = "I915_PERF_OPEN", [DRM_COMMAND_BASE + 0x37] = "I915_PERF_ADD_CONFIG", [DRM_COMMAND_BASE + 0x38] = "I915_PERF_REMOVE_CONFIG", + [DRM_COMMAND_BASE + 0x39] = "I915_QUERY", }; I.e. on systems where this is used it will appear when, for instance, one does a system wide 'perf trace' session looking for ioctl calls, just like it does with the previously implemented DRM_I915 ioctls: # perf trace -e ioctl --filter-pids 2190 4346.232 ( 0.012 ms): gnome-shell/1455 ioctl(fd: 8, cmd: DRM_I915_GEM_BUSY, arg: 0x7fff3b0cd910) = 0 4346.246 ( 0.002 ms): gnome-shell/1455 ioctl(fd: 8, cmd: DRM_I915_GEM_MADVISE, arg: 0x7fff3b0cd980) = 0 4346.252 ( 0.002 ms): gnome-shell/1455 ioctl(fd: 8, cmd: DRM_I915_GEM_BUSY, arg: 0x7fff3b0cdb00) = 0 This silences this perf tools build warning: Warning: Kernel ABI header at 'tools/include/uapi/drm/i915_drm.h' differs from latest version at 'include/uapi/drm/i915_drm.h' Cc: Adrian Hunter Cc: Chris Wilson Cc: David Ahern Cc: Jiri Olsa Cc: Joonas Lahtinen Cc: Lionel Landwerlin Cc: Namhyung Kim Cc: Tvrtko Ursulin Cc: Wang Nan Link: https://lkml.kernel.org/n/tip-5kxuvruuzdbojvf90f8j2wat@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/include/uapi/drm/i915_drm.h | 112 ++++++++++++++++++++++++++++-- 1 file changed, 108 insertions(+), 4 deletions(-) diff --git a/tools/include/uapi/drm/i915_drm.h b/tools/include/uapi/drm/i915_drm.h index 536ee4febd74..7f5634ce8e88 100644 --- a/tools/include/uapi/drm/i915_drm.h +++ b/tools/include/uapi/drm/i915_drm.h @@ -318,6 +318,7 @@ typedef struct _drm_i915_sarea { #define DRM_I915_PERF_OPEN 0x36 #define DRM_I915_PERF_ADD_CONFIG 0x37 #define DRM_I915_PERF_REMOVE_CONFIG 0x38 +#define DRM_I915_QUERY 0x39 #define DRM_IOCTL_I915_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t) #define DRM_IOCTL_I915_FLUSH DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLUSH) @@ -375,6 +376,7 @@ typedef struct _drm_i915_sarea { #define DRM_IOCTL_I915_PERF_OPEN DRM_IOW(DRM_COMMAND_BASE + DRM_I915_PERF_OPEN, struct drm_i915_perf_open_param) #define DRM_IOCTL_I915_PERF_ADD_CONFIG DRM_IOW(DRM_COMMAND_BASE + DRM_I915_PERF_ADD_CONFIG, struct drm_i915_perf_oa_config) #define DRM_IOCTL_I915_PERF_REMOVE_CONFIG DRM_IOW(DRM_COMMAND_BASE + DRM_I915_PERF_REMOVE_CONFIG, __u64) +#define DRM_IOCTL_I915_QUERY DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_QUERY, struct drm_i915_query) /* Allow drivers to submit batchbuffers directly to hardware, relying * on the security mechanisms provided by hardware. @@ -1358,7 +1360,9 @@ struct drm_intel_overlay_attrs { * active on a given plane. */ -#define I915_SET_COLORKEY_NONE (1<<0) /* disable color key matching */ +#define I915_SET_COLORKEY_NONE (1<<0) /* Deprecated. Instead set + * flags==0 to disable colorkeying. + */ #define I915_SET_COLORKEY_DESTINATION (1<<1) #define I915_SET_COLORKEY_SOURCE (1<<2) struct drm_intel_sprite_colorkey { @@ -1604,15 +1608,115 @@ struct drm_i915_perf_oa_config { __u32 n_flex_regs; /* - * These fields are pointers to tuples of u32 values (register - * address, value). For example the expected length of the buffer - * pointed by mux_regs_ptr is (2 * sizeof(u32) * n_mux_regs). + * These fields are pointers to tuples of u32 values (register address, + * value). For example the expected length of the buffer pointed by + * mux_regs_ptr is (2 * sizeof(u32) * n_mux_regs). */ __u64 mux_regs_ptr; __u64 boolean_regs_ptr; __u64 flex_regs_ptr; }; +struct drm_i915_query_item { + __u64 query_id; +#define DRM_I915_QUERY_TOPOLOGY_INFO 1 + + /* + * When set to zero by userspace, this is filled with the size of the + * data to be written at the data_ptr pointer. The kernel sets this + * value to a negative value to signal an error on a particular query + * item. + */ + __s32 length; + + /* + * Unused for now. Must be cleared to zero. + */ + __u32 flags; + + /* + * Data will be written at the location pointed by data_ptr when the + * value of length matches the length of the data to be written by the + * kernel. + */ + __u64 data_ptr; +}; + +struct drm_i915_query { + __u32 num_items; + + /* + * Unused for now. Must be cleared to zero. + */ + __u32 flags; + + /* + * This points to an array of num_items drm_i915_query_item structures. + */ + __u64 items_ptr; +}; + +/* + * Data written by the kernel with query DRM_I915_QUERY_TOPOLOGY_INFO : + * + * data: contains the 3 pieces of information : + * + * - the slice mask with one bit per slice telling whether a slice is + * available. The availability of slice X can be queried with the following + * formula : + * + * (data[X / 8] >> (X % 8)) & 1 + * + * - the subslice mask for each slice with one bit per subslice telling + * whether a subslice is available. The availability of subslice Y in slice + * X can be queried with the following formula : + * + * (data[subslice_offset + + * X * subslice_stride + + * Y / 8] >> (Y % 8)) & 1 + * + * - the EU mask for each subslice in each slice with one bit per EU telling + * whether an EU is available. The availability of EU Z in subslice Y in + * slice X can be queried with the following formula : + * + * (data[eu_offset + + * (X * max_subslices + Y) * eu_stride + + * Z / 8] >> (Z % 8)) & 1 + */ +struct drm_i915_query_topology_info { + /* + * Unused for now. Must be cleared to zero. + */ + __u16 flags; + + __u16 max_slices; + __u16 max_subslices; + __u16 max_eus_per_subslice; + + /* + * Offset in data[] at which the subslice masks are stored. + */ + __u16 subslice_offset; + + /* + * Stride at which each of the subslice masks for each slice are + * stored. + */ + __u16 subslice_stride; + + /* + * Offset in data[] at which the EU masks are stored. + */ + __u16 eu_offset; + + /* + * Stride at which each of the EU masks for each subslice are stored. + */ + __u16 eu_stride; + + __u8 data[]; +}; + #if defined(__cplusplus) } #endif From b238db655796e74b59d9ece58b645ad0b494d615 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Tue, 6 Mar 2018 11:13:18 +0200 Subject: [PATCH 25/36] perf auxtrace: Make auxtrace_queues__add_buffer() do CPU filtering In preparation for supporting AUX area sampling buffers, auxtrace_queues__add_buffer() needs to be more generic. To that end, move CPU filtering into it. Signed-off-by: Adrian Hunter Cc: Jiri Olsa Link: http://lkml.kernel.org/r/1520327598-1317-8-git-send-email-adrian.hunter@intel.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/auxtrace.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/tools/perf/util/auxtrace.c b/tools/perf/util/auxtrace.c index e1aff91c54a8..857de69a5361 100644 --- a/tools/perf/util/auxtrace.c +++ b/tools/perf/util/auxtrace.c @@ -302,6 +302,13 @@ static int auxtrace_queues__split_buffer(struct auxtrace_queues *queues, return 0; } +static bool filter_cpu(struct perf_session *session, int cpu) +{ + unsigned long *cpu_bitmap = session->itrace_synth_opts->cpu_bitmap; + + return cpu_bitmap && cpu != -1 && !test_bit(cpu, cpu_bitmap); +} + static int auxtrace_queues__add_buffer(struct auxtrace_queues *queues, struct perf_session *session, unsigned int idx, @@ -310,6 +317,9 @@ static int auxtrace_queues__add_buffer(struct auxtrace_queues *queues, { int err = -ENOMEM; + if (filter_cpu(session, buffer->cpu)) + return 0; + buffer = memdup(buffer, sizeof(*buffer)); if (!buffer) return -ENOMEM; @@ -344,13 +354,6 @@ out_free: return err; } -static bool filter_cpu(struct perf_session *session, int cpu) -{ - unsigned long *cpu_bitmap = session->itrace_synth_opts->cpu_bitmap; - - return cpu_bitmap && cpu != -1 && !test_bit(cpu, cpu_bitmap); -} - int auxtrace_queues__add_event(struct auxtrace_queues *queues, struct perf_session *session, union perf_event *event, off_t data_offset, @@ -367,9 +370,6 @@ int auxtrace_queues__add_event(struct auxtrace_queues *queues, }; unsigned int idx = event->auxtrace.idx; - if (filter_cpu(session, event->auxtrace.cpu)) - return 0; - return auxtrace_queues__add_buffer(queues, session, idx, &buffer, buffer_ptr); } From fdae6400809aa179f8ca04e32f3eb176fb3b3a9d Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Fri, 6 Apr 2018 11:56:11 -0300 Subject: [PATCH 26/36] perf hists browser: Show extra_title_lines in the 'D' debug hotkey To help in fixing problems in the browser. Cc: Adrian Hunter Cc: David Ahern Cc: Jiri Olsa Cc: Namhyung Kim Cc: Wang Nan Link: https://lkml.kernel.org/n/tip-uj0n76yqh5bf98i0edckd47t@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/ui/browsers/hists.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c index b06afb8f51fb..de17e59d9952 100644 --- a/tools/perf/ui/browsers/hists.c +++ b/tools/perf/ui/browsers/hists.c @@ -659,9 +659,10 @@ int hist_browser__run(struct hist_browser *browser, const char *help, struct hist_entry *h = rb_entry(browser->b.top, struct hist_entry, rb_node); ui_helpline__pop(); - ui_helpline__fpush("%d: nr_ent=(%d,%d), rows=%d, idx=%d, fve: idx=%d, row_off=%d, nrows=%d", + ui_helpline__fpush("%d: nr_ent=(%d,%d), etl: %d, rows=%d, idx=%d, fve: idx=%d, row_off=%d, nrows=%d", seq++, browser->b.nr_entries, browser->hists->nr_entries, + browser->b.extra_title_lines, browser->b.rows, browser->b.index, browser->b.top_idx, From 94e87a8bd529121ea90219164c65c36ea1d19e56 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Fri, 6 Apr 2018 12:11:11 -0300 Subject: [PATCH 27/36] perf hists browser: Remove leftover from row returned from refresh MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The per-browser screen refresh routine (ui_browser->refresh()) should return the first row that should be cleaned after the rows just printed, in case not all rows available on the screen gets filled. When moving the extra title lines logic from the hists browser to the generic ui_browser class, one piece of that logic remained in the hists browser and then when going back from the annotate browser to the hists browser in a case where fewer lines were displayed in the hists browser, for instance when filtering the entries per substring, one line of the annotate browser would remain on the screen, fix that. Example of the screen artifact: ================================================================================ Samples: 73K of event 'cycles:ppp', 4000 Hz, Event count (approx.): 45172901394 Overhead Shared O Symbol 0.30% [kernel] [k] __indirect_thunk_start 0.09% [kernel] [k] __x86_indirect_thunk_r10 │ lfence ================================================================================ Here from 'perf top' the view was zoomed with '/thunk' to functions having that substring, then the first was annotated and from the annotate browser ESC was pressed, then the first lines were overwritten, but the 'lfence' line remained due to the off by one bug fixed in this cset. Cc: Adrian Hunter Cc: Andi Kleen Cc: David Ahern Cc: Jin Yao Cc: Jiri Olsa Cc: Namhyung Kim Cc: Wang Nan Fixes: ef9ff6017e3c ("perf ui browser: Move the extra title lines from the hists browser") Link: https://lkml.kernel.org/n/tip-odryfso74eaarm0z3e4v9owx@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/ui/browsers/hists.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c index de17e59d9952..0eec06c105c6 100644 --- a/tools/perf/ui/browsers/hists.c +++ b/tools/perf/ui/browsers/hists.c @@ -1744,17 +1744,11 @@ static void ui_browser__hists_init_top(struct ui_browser *browser) static unsigned int hist_browser__refresh(struct ui_browser *browser) { unsigned row = 0; - u16 header_offset = 0; struct rb_node *nd; struct hist_browser *hb = container_of(browser, struct hist_browser, b); - struct hists *hists = hb->hists; - - if (hb->show_headers) { - struct perf_hpp_list *hpp_list = hists->hpp_list; + if (hb->show_headers) hist_browser__show_headers(hb); - header_offset = hpp_list->nr_header_lines; - } ui_browser__hists_init_top(browser); hb->he_selection = NULL; @@ -1792,7 +1786,7 @@ static unsigned int hist_browser__refresh(struct ui_browser *browser) break; } - return row + header_offset; + return row; } static struct rb_node *hists__filter_entries(struct rb_node *nd, From ad0902e0c4004dc95bf15229933012121ff54033 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Fri, 6 Apr 2018 14:53:56 -0300 Subject: [PATCH 28/36] perf tools: No need to include namespaces.h in util.h The only thing that is needed there is a forward declaration for 'struct nsinfo', so disentanble this, which in turns allows built-in clang builds, i.e. 'make LIBCLANGLLVM=1 -C tools/perf'. Cc: Adrian Hunter Cc: David Ahern Cc: Jiri Olsa Cc: Namhyung Kim Cc: Naveen N. Rao Cc: Sandipan Das Cc: Wang Nan Link: https://lkml.kernel.org/n/tip-vq26rsuwq1cqylpcyvq89c84@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/util.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h index 9496365da3d7..c9626c206208 100644 --- a/tools/perf/util/util.h +++ b/tools/perf/util/util.h @@ -11,8 +11,7 @@ #include #include #include -#include -#include "namespaces.h" +#include /* General helper functions */ void usage(const char *err) __noreturn; @@ -26,6 +25,7 @@ static inline void *zalloc(size_t size) #define zfree(ptr) ({ free(*ptr); *ptr = NULL; }) struct dirent; +struct nsinfo; struct strlist; int mkdir_p(char *path, mode_t mode); From c2fb54a183cfe77c6fdc9d71e2d5299c1c302a6e Mon Sep 17 00:00:00 2001 From: Sandipan Das Date: Wed, 4 Apr 2018 23:34:17 +0530 Subject: [PATCH 29/36] perf tools: Fix perf builds with clang support For libclang, some distro packages provide static libraries (.a) while some provide shared libraries (.so). Currently, perf code can only be linked with static libraries. This makes perf build possible for both cases. Signed-off-by: Sandipan Das Cc: Jiri Olsa Cc: Naveen N. Rao Fixes: d58ac0bf8d1e ("perf build: Add clang and llvm compile and linking support") Link: http://lkml.kernel.org/r/20180404180419.19056-1-sandipan@linux.vnet.ibm.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/Makefile.perf | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf index f7517e1b73f8..83e453de36f8 100644 --- a/tools/perf/Makefile.perf +++ b/tools/perf/Makefile.perf @@ -364,7 +364,8 @@ LIBS = -Wl,--whole-archive $(PERFLIBS) $(EXTRA_PERFLIBS) -Wl,--no-whole-archive ifeq ($(USE_CLANG), 1) CLANGLIBS_LIST = AST Basic CodeGen Driver Frontend Lex Tooling Edit Sema Analysis Parse Serialization - LIBCLANG = $(foreach l,$(CLANGLIBS_LIST),$(wildcard $(shell $(LLVM_CONFIG) --libdir)/libclang$(l).a)) + CLANGLIBS_NOEXT_LIST = $(foreach l,$(CLANGLIBS_LIST),$(shell $(LLVM_CONFIG) --libdir)/libclang$(l)) + LIBCLANG = $(foreach l,$(CLANGLIBS_NOEXT_LIST),$(wildcard $(l).a $(l).so)) LIBS += -Wl,--start-group $(LIBCLANG) -Wl,--end-group endif From 7854e499f33fd9c7e63288692ffb754d9b1d02fd Mon Sep 17 00:00:00 2001 From: Sandipan Das Date: Wed, 4 Apr 2018 23:34:18 +0530 Subject: [PATCH 30/36] perf clang: Add support for recent clang versions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The clang API calls used by perf have changed in recent releases and builds succeed with libclang-3.9 only. This introduces compatibility with libclang-4.0 and above. Without this patch, we will see the following compilation errors with libclang-4.0+: util/c++/clang.cpp: In function ‘clang::CompilerInvocation* perf::createCompilerInvocation(llvm::opt::ArgStringList, llvm::StringRef&, clang::DiagnosticsEngine&)’: util/c++/clang.cpp:62:33: error: ‘IK_C’ was not declared in this scope Opts.Inputs.emplace_back(Path, IK_C); ^~~~ util/c++/clang.cpp: In function ‘std::unique_ptr perf::getModuleFromSource(llvm::opt::ArgStringList, llvm::StringRef, llvm::IntrusiveRefCntPtr)’: util/c++/clang.cpp:75:26: error: no matching function for call to ‘clang::CompilerInstance::setInvocation(clang::CompilerInvocation*)’ Clang.setInvocation(&*CI); ^ In file included from util/c++/clang.cpp:14:0: /usr/include/clang/Frontend/CompilerInstance.h:231:8: note: candidate: void clang::CompilerInstance::setInvocation(std::shared_ptr) void setInvocation(std::shared_ptr Value); ^~~~~~~~~~~~~ Committer testing: Tested on Fedora 27 after installing the clang-devel and llvm-devel packages, versions: # rpm -qa | egrep llvm\|clang llvm-5.0.1-6.fc27.x86_64 clang-libs-5.0.1-5.fc27.x86_64 clang-5.0.1-5.fc27.x86_64 clang-tools-extra-5.0.1-5.fc27.x86_64 llvm-libs-5.0.1-6.fc27.x86_64 llvm-devel-5.0.1-6.fc27.x86_64 clang-devel-5.0.1-5.fc27.x86_64 # Make sure you don't have some older version lying around in /usr/local, etc, then: $ make LIBCLANGLLVM=1 -C tools/perf install-bin And in the end perf will be linked agains these libraries: # ldd ~/bin/perf | egrep -i llvm\|clang libclangAST.so.5 => /lib64/libclangAST.so.5 (0x00007f8bb2eb4000) libclangBasic.so.5 => /lib64/libclangBasic.so.5 (0x00007f8bb29e3000) libclangCodeGen.so.5 => /lib64/libclangCodeGen.so.5 (0x00007f8bb23f7000) libclangDriver.so.5 => /lib64/libclangDriver.so.5 (0x00007f8bb2060000) libclangFrontend.so.5 => /lib64/libclangFrontend.so.5 (0x00007f8bb1d06000) libclangLex.so.5 => /lib64/libclangLex.so.5 (0x00007f8bb1a3e000) libclangTooling.so.5 => /lib64/libclangTooling.so.5 (0x00007f8bb17d4000) libclangEdit.so.5 => /lib64/libclangEdit.so.5 (0x00007f8bb15c5000) libclangSema.so.5 => /lib64/libclangSema.so.5 (0x00007f8bb0cc9000) libclangAnalysis.so.5 => /lib64/libclangAnalysis.so.5 (0x00007f8bb0a23000) libclangParse.so.5 => /lib64/libclangParse.so.5 (0x00007f8bb0725000) libclangSerialization.so.5 => /lib64/libclangSerialization.so.5 (0x00007f8bb039a000) libLLVM-5.0.so => /lib64/libLLVM-5.0.so (0x00007f8bace98000) libclangASTMatchers.so.5 => /lib64/../lib64/libclangASTMatchers.so.5 (0x00007f8bab735000) libclangFormat.so.5 => /lib64/../lib64/libclangFormat.so.5 (0x00007f8bab4b2000) libclangRewrite.so.5 => /lib64/../lib64/libclangRewrite.so.5 (0x00007f8bab2a1000) libclangToolingCore.so.5 => /lib64/../lib64/libclangToolingCore.so.5 (0x00007f8bab08e000) # Signed-off-by: Sandipan Das Tested-by: Arnaldo Carvalho de Melo Cc: Jiri Olsa Cc: Naveen N. Rao Fixes: 00b86691c77c ("perf clang: Add builtin clang support ant test case") Link: http://lkml.kernel.org/r/20180404180419.19056-2-sandipan@linux.vnet.ibm.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/c++/clang.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/tools/perf/util/c++/clang.cpp b/tools/perf/util/c++/clang.cpp index 1bfc946e37dc..bf31ceab33bd 100644 --- a/tools/perf/util/c++/clang.cpp +++ b/tools/perf/util/c++/clang.cpp @@ -9,6 +9,7 @@ * Copyright (C) 2016 Huawei Inc. */ +#include "clang/Basic/Version.h" #include "clang/CodeGen/CodeGenAction.h" #include "clang/Frontend/CompilerInvocation.h" #include "clang/Frontend/CompilerInstance.h" @@ -58,7 +59,8 @@ createCompilerInvocation(llvm::opt::ArgStringList CFlags, StringRef& Path, FrontendOptions& Opts = CI->getFrontendOpts(); Opts.Inputs.clear(); - Opts.Inputs.emplace_back(Path, IK_C); + Opts.Inputs.emplace_back(Path, + FrontendOptions::getInputKindForExtension("c")); return CI; } @@ -71,10 +73,17 @@ getModuleFromSource(llvm::opt::ArgStringList CFlags, Clang.setVirtualFileSystem(&*VFS); +#if CLANG_VERSION_MAJOR < 4 IntrusiveRefCntPtr CI = createCompilerInvocation(std::move(CFlags), Path, Clang.getDiagnostics()); Clang.setInvocation(&*CI); +#else + std::shared_ptr CI( + createCompilerInvocation(std::move(CFlags), Path, + Clang.getDiagnostics())); + Clang.setInvocation(CI); +#endif std::unique_ptr Act(new EmitLLVMOnlyAction(&*LLVMCtx)); if (!Clang.ExecuteAction(*Act)) From fcbd8fa44664e99a5d8c7ab97f1afdd82472f973 Mon Sep 17 00:00:00 2001 From: Sandipan Das Date: Wed, 4 Apr 2018 23:34:19 +0530 Subject: [PATCH 31/36] perf tests clang: Fix function name for clang IR test As stated in tests/llvm-src-base.c, the name of the bpf function should be "bpf_func__SyS_epoll_pwait" but this clang test fails as it tries to lookup "bpf_func__SyS_epoll_wait". Before applying patch: 55: builtin clang support : 55.1: builtin clang compile C source to IR : FAILED! 55.2: builtin clang compile C source to ELF object : Skip After applying patch: 55: builtin clang support : 55.1: builtin clang compile C source to IR : Ok 55.2: builtin clang compile C source to ELF object : Ok Signed-off-by: Sandipan Das Tested-by: Arnaldo Carvalho de Melo Cc: Jiri Olsa Cc: Naveen N. Rao Fixes: e67d52d411c3 ("perf clang: Update test case to use real BPF script") Link: http://lkml.kernel.org/r/20180404180419.19056-3-sandipan@linux.vnet.ibm.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/c++/clang-test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/perf/util/c++/clang-test.cpp b/tools/perf/util/c++/clang-test.cpp index a4014d786676..7b042a5ebc68 100644 --- a/tools/perf/util/c++/clang-test.cpp +++ b/tools/perf/util/c++/clang-test.cpp @@ -41,7 +41,7 @@ int test__clang_to_IR(void) if (!M) return -1; for (llvm::Function& F : *M) - if (F.getName() == "bpf_func__SyS_epoll_wait") + if (F.getName() == "bpf_func__SyS_epoll_pwait") return 0; return -1; } From 621b6d2ea297d0fb6030452c5bcd221f12165fcf Mon Sep 17 00:00:00 2001 From: Prashant Bhole Date: Mon, 9 Apr 2018 19:03:46 +0900 Subject: [PATCH 32/36] perf/core: Fix use-after-free in uprobe_perf_close() A use-after-free bug was caught by KASAN while running usdt related code (BCC project. bcc/tests/python/test_usdt2.py): ================================================================== BUG: KASAN: use-after-free in uprobe_perf_close+0x222/0x3b0 Read of size 4 at addr ffff880384f9b4a4 by task test_usdt2.py/870 CPU: 4 PID: 870 Comm: test_usdt2.py Tainted: G W 4.16.0-next-20180409 #215 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Ubuntu-1.8.2-1ubuntu1 04/01/2014 Call Trace: dump_stack+0xc7/0x15b ? show_regs_print_info+0x5/0x5 ? printk+0x9c/0xc3 ? kmsg_dump_rewind_nolock+0x6e/0x6e ? uprobe_perf_close+0x222/0x3b0 print_address_description+0x83/0x3a0 ? uprobe_perf_close+0x222/0x3b0 kasan_report+0x1dd/0x460 ? uprobe_perf_close+0x222/0x3b0 uprobe_perf_close+0x222/0x3b0 ? probes_open+0x180/0x180 ? free_filters_list+0x290/0x290 trace_uprobe_register+0x1bb/0x500 ? perf_event_attach_bpf_prog+0x310/0x310 ? probe_event_disable+0x4e0/0x4e0 perf_uprobe_destroy+0x63/0xd0 _free_event+0x2bc/0xbd0 ? lockdep_rcu_suspicious+0x100/0x100 ? ring_buffer_attach+0x550/0x550 ? kvm_sched_clock_read+0x1a/0x30 ? perf_event_release_kernel+0x3e4/0xc00 ? __mutex_unlock_slowpath+0x12e/0x540 ? wait_for_completion+0x430/0x430 ? lock_downgrade+0x3c0/0x3c0 ? lock_release+0x980/0x980 ? do_raw_spin_trylock+0x118/0x150 ? do_raw_spin_unlock+0x121/0x210 ? do_raw_spin_trylock+0x150/0x150 perf_event_release_kernel+0x5d4/0xc00 ? put_event+0x30/0x30 ? fsnotify+0xd2d/0xea0 ? sched_clock_cpu+0x18/0x1a0 ? __fsnotify_update_child_dentry_flags.part.0+0x1b0/0x1b0 ? pvclock_clocksource_read+0x152/0x2b0 ? pvclock_read_flags+0x80/0x80 ? kvm_sched_clock_read+0x1a/0x30 ? sched_clock_cpu+0x18/0x1a0 ? pvclock_clocksource_read+0x152/0x2b0 ? locks_remove_file+0xec/0x470 ? pvclock_read_flags+0x80/0x80 ? fcntl_setlk+0x880/0x880 ? ima_file_free+0x8d/0x390 ? lockdep_rcu_suspicious+0x100/0x100 ? ima_file_check+0x110/0x110 ? fsnotify+0xea0/0xea0 ? kvm_sched_clock_read+0x1a/0x30 ? rcu_note_context_switch+0x600/0x600 perf_release+0x21/0x40 __fput+0x264/0x620 ? fput+0xf0/0xf0 ? do_raw_spin_unlock+0x121/0x210 ? do_raw_spin_trylock+0x150/0x150 ? SyS_fchdir+0x100/0x100 ? fsnotify+0xea0/0xea0 task_work_run+0x14b/0x1e0 ? task_work_cancel+0x1c0/0x1c0 ? copy_fd_bitmaps+0x150/0x150 ? vfs_read+0xe5/0x260 exit_to_usermode_loop+0x17b/0x1b0 ? trace_event_raw_event_sys_exit+0x1a0/0x1a0 do_syscall_64+0x3f6/0x490 ? syscall_return_slowpath+0x2c0/0x2c0 ? lockdep_sys_exit+0x1f/0xaa ? syscall_return_slowpath+0x1a3/0x2c0 ? lockdep_sys_exit+0x1f/0xaa ? prepare_exit_to_usermode+0x11c/0x1e0 ? enter_from_user_mode+0x30/0x30 random: crng init done ? __put_user_4+0x1c/0x30 entry_SYSCALL_64_after_hwframe+0x3d/0xa2 RIP: 0033:0x7f41d95f9340 RSP: 002b:00007fffe71e4268 EFLAGS: 00000246 ORIG_RAX: 0000000000000003 RAX: 0000000000000000 RBX: 000000000000000d RCX: 00007f41d95f9340 RDX: 0000000000000000 RSI: 0000000000002401 RDI: 000000000000000d RBP: 0000000000000000 R08: 00007f41ca8ff700 R09: 00007f41d996dd1f R10: 00007fffe71e41e0 R11: 0000000000000246 R12: 00007fffe71e4330 R13: 0000000000000000 R14: fffffffffffffffc R15: 00007fffe71e4290 Allocated by task 870: kasan_kmalloc+0xa0/0xd0 kmem_cache_alloc_node+0x11a/0x430 copy_process.part.19+0x11a0/0x41c0 _do_fork+0x1be/0xa20 do_syscall_64+0x198/0x490 entry_SYSCALL_64_after_hwframe+0x3d/0xa2 Freed by task 0: __kasan_slab_free+0x12e/0x180 kmem_cache_free+0x102/0x4d0 free_task+0xfe/0x160 __put_task_struct+0x189/0x290 delayed_put_task_struct+0x119/0x250 rcu_process_callbacks+0xa6c/0x1b60 __do_softirq+0x238/0x7ae The buggy address belongs to the object at ffff880384f9b480 which belongs to the cache task_struct of size 12928 It occurs because task_struct is freed before perf_event which refers to the task and task flags are checked while teardown of the event. perf_event_alloc() assigns task_struct to hw.target of perf_event, but there is no reference counting for it. As a fix we get_task_struct() in perf_event_alloc() at above mentioned assignment and put_task_struct() in _free_event(). Signed-off-by: Prashant Bhole Reviewed-by: Oleg Nesterov Acked-by: Peter Zijlstra (Intel) Cc: Cc: Alexander Shishkin Cc: Arnaldo Carvalho de Melo Cc: Jiri Olsa Cc: Linus Torvalds Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Thomas Gleixner Fixes: 63b6da39bb38e8f1a1ef3180d32a39d6 ("perf: Fix perf_event_exit_task() race") Link: http://lkml.kernel.org/r/20180409100346.6416-1-bhole_prashant_q7@lab.ntt.co.jp Signed-off-by: Ingo Molnar --- kernel/events/core.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/kernel/events/core.c b/kernel/events/core.c index fc1c330c6bd6..d7af82827373 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -4447,6 +4447,9 @@ static void _free_event(struct perf_event *event) if (event->ctx) put_ctx(event->ctx); + if (event->hw.target) + put_task_struct(event->hw.target); + exclusive_event_destroy(event); module_put(event->pmu->module); @@ -9955,6 +9958,7 @@ perf_event_alloc(struct perf_event_attr *attr, int cpu, * and we cannot use the ctx information because we need the * pmu before we get a ctx. */ + get_task_struct(task); event->hw.target = task; } @@ -10070,6 +10074,8 @@ err_ns: perf_detach_cgroup(event); if (event->ns) put_pid_ns(event->ns); + if (event->hw.target) + put_task_struct(event->hw.target); kfree(event); return ERR_PTR(err); From 5da13ab8b0dcaa984c45ae43edf5a4d148603d42 Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu Date: Mon, 9 Apr 2018 21:16:54 +0900 Subject: [PATCH 33/36] perf/core: Fix perf_kprobe_init() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix error handling in perf_kprobe_init(): ================================================================== BUG: KASAN: slab-out-of-bounds in strlen+0x8e/0xa0 lib/string.c:482 Read of size 1 at addr ffff88003f9cc5c0 by task syz-executor2/23095 CPU: 0 PID: 23095 Comm: syz-executor2 Not tainted 4.16.0+ #24 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Ubuntu-1.8.2-1ubuntu1 04/01/2014 Call Trace: __dump_stack lib/dump_stack.c:77 [inline] dump_stack+0xca/0x13e lib/dump_stack.c:113 print_address_description+0x6e/0x2c0 mm/kasan/report.c:256 kasan_report_error mm/kasan/report.c:354 [inline] kasan_report+0x256/0x380 mm/kasan/report.c:412 strlen+0x8e/0xa0 lib/string.c:482 kstrdup+0x21/0x70 mm/util.c:55 alloc_trace_kprobe+0xc8/0x930 kernel/trace/trace_kprobe.c:325 create_local_trace_kprobe+0x4f/0x3a0 kernel/trace/trace_kprobe.c:1438 perf_kprobe_init+0x149/0x1f0 kernel/trace/trace_event_perf.c:264 perf_kprobe_event_init+0xa8/0x120 kernel/events/core.c:8407 perf_try_init_event+0xcb/0x2a0 kernel/events/core.c:9719 perf_init_event kernel/events/core.c:9750 [inline] perf_event_alloc+0x1367/0x1e20 kernel/events/core.c:10022 SYSC_perf_event_open+0x242/0x2330 kernel/events/core.c:10477 do_syscall_64+0x198/0x640 arch/x86/entry/common.c:287 entry_SYSCALL_64_after_hwframe+0x42/0xb7 Reported-by: 范龙飞 Signed-off-by: Masami Hiramatsu Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Song Liu Cc: Thomas Gleixner Fixes: e12f03d7031a ("perf/core: Implement the 'perf_kprobe' PMU") Signed-off-by: Ingo Molnar --- kernel/trace/trace_event_perf.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/kernel/trace/trace_event_perf.c b/kernel/trace/trace_event_perf.c index 2c416509b834..94600f1f7efa 100644 --- a/kernel/trace/trace_event_perf.c +++ b/kernel/trace/trace_event_perf.c @@ -252,6 +252,8 @@ int perf_kprobe_init(struct perf_event *p_event, bool is_retprobe) ret = strncpy_from_user( func, u64_to_user_ptr(p_event->attr.kprobe_func), KSYM_NAME_LEN); + if (ret == KSYM_NAME_LEN) + ret = -E2BIG; if (ret < 0) goto out; From 0eadcc7a7bc03e991d2da1cf88143fb7cc0342c1 Mon Sep 17 00:00:00 2001 From: Song Liu Date: Mon, 9 Apr 2018 18:31:30 +0000 Subject: [PATCH 34/36] perf/core: Fix perf_uprobe_init() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Similarly to the uprobe PMU fix in perf_kprobe_init(), fix error handling in perf_uprobe_init() as well. Reported-by: 范龙飞 Signed-off-by: Song Liu Acked-by: Masami Hiramatsu Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Fixes: e12f03d7031a ("perf/core: Implement the 'perf_kprobe' PMU") Signed-off-by: Ingo Molnar --- kernel/trace/trace_event_perf.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/kernel/trace/trace_event_perf.c b/kernel/trace/trace_event_perf.c index 94600f1f7efa..c79193e598f5 100644 --- a/kernel/trace/trace_event_perf.c +++ b/kernel/trace/trace_event_perf.c @@ -302,6 +302,8 @@ int perf_uprobe_init(struct perf_event *p_event, bool is_retprobe) return -ENOMEM; ret = strncpy_from_user( path, u64_to_user_ptr(p_event->attr.uprobe_path), PATH_MAX); + if (ret == PATH_MAX) + return -E2BIG; if (ret < 0) goto out; if (path[0] == '\0') { From 50268a3d266ecfdd6c5873d62b2758d9732fc598 Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu Date: Tue, 10 Apr 2018 21:20:08 +0900 Subject: [PATCH 35/36] tracing/uprobe_event: Fix strncpy corner case MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix string fetch function to terminate with NUL. It is OK to drop the rest of string. Signed-off-by: Masami Hiramatsu Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Song Liu Cc: Thomas Gleixner Cc: security@kernel.org Cc: 范龙飞 Fixes: 5baaa59ef09e ("tracing/probes: Implement 'memory' fetch method for uprobes") Signed-off-by: Ingo Molnar --- kernel/trace/trace_uprobe.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/kernel/trace/trace_uprobe.c b/kernel/trace/trace_uprobe.c index 2014f4351ae0..0d450b40988e 100644 --- a/kernel/trace/trace_uprobe.c +++ b/kernel/trace/trace_uprobe.c @@ -151,6 +151,8 @@ static void FETCH_FUNC_NAME(memory, string)(struct pt_regs *regs, return; ret = strncpy_from_user(dst, src, maxlen); + if (ret == maxlen) + dst[--ret] = '\0'; if (ret < 0) { /* Failed to fetch string */ ((u8 *)get_rloc_data(dest))[0] = '\0'; From 32e6e967fb36bf77ed99221ae3ce1909f045d8f9 Mon Sep 17 00:00:00 2001 From: Song Liu Date: Wed, 11 Apr 2018 18:02:37 +0000 Subject: [PATCH 36/36] perf/core: Need CAP_SYS_ADMIN to create k/uprobe with perf_event_open() Non-root user cannot create kprobe or uprobe through the text-based interface (kprobe_events, uprobe_events),so they should not be able to create probes via perf_event_open() either. Reported-by: Vince Weaver Signed-off-by: Song Liu Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Fixes: 33ea4b24277b ("perf/core: Implement the 'perf_uprobe' PMU") Fixes: e12f03d7031a ("perf/core: Implement the 'perf_kprobe' PMU") Link: http://lkml.kernel.org/r/C0B2EFB5-C403-4BDB-9046-C14B3EE66999@fb.com Signed-off-by: Ingo Molnar --- kernel/events/core.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/kernel/events/core.c b/kernel/events/core.c index d7af82827373..2d5fe26551f8 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -8400,6 +8400,10 @@ static int perf_kprobe_event_init(struct perf_event *event) if (event->attr.type != perf_kprobe.type) return -ENOENT; + + if (!capable(CAP_SYS_ADMIN)) + return -EACCES; + /* * no branch sampling for probe events */ @@ -8437,6 +8441,10 @@ static int perf_uprobe_event_init(struct perf_event *event) if (event->attr.type != perf_uprobe.type) return -ENOENT; + + if (!capable(CAP_SYS_ADMIN)) + return -EACCES; + /* * no branch sampling for probe events */