aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2018-04-15 15:36:31 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2018-04-15 15:36:31 -0400
commit174e719439b8224d7cedfbdd9529de396cac01ff (patch)
treea1729ca869e7dedaa47199d0818b2297521076a5
parent19ca90de49c3269874722148edf07083182e23ec (diff)
parent32e6e967fb36bf77ed99221ae3ce1909f045d8f9 (diff)
Merge branch 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull more perf updates from Thomas Gleixner: "A rather large set of perf updates: Kernel: - Fix various initialization issues - Prevent creating [ku]probes for not CAP_SYS_ADMIN users Tooling: - Show only failing syscalls with 'perf trace --failure' (Arnaldo Carvalho de Melo) e.g: See what 'openat' syscalls are failing: # perf trace --failure -e openat 762.323 ( 0.007 ms): VideoCapture/4566 openat(dfd: CWD, filename: /dev/video2) = -1 ENOENT No such file or directory <SNIP N /dev/videoN open attempts... sigh, where is that improvised camera lid?!? > 790.228 ( 0.008 ms): VideoCapture/4566 openat(dfd: CWD, filename: /dev/video63) = -1 ENOENT No such file or directory ^C# - Show information about the event (freq, nr_samples, total period/nr_events) in the annotate --tui and --stdio2 'perf annotate' output, similar to the first line in the 'perf report --tui', but just for the samples for a the annotated symbol (Arnaldo Carvalho de Melo) - Introduce 'perf version --build-options' to show what features were linked, aliased as well as a shorter 'perf -vv' (Jin Yao) - Add a "dso_size" sort order (Kim Phillips) - Remove redundant ')' in the tracepoint output in 'perf trace' (Changbin Du) - Synchronize x86's cpufeatures.h, no effect on toolss (Arnaldo Carvalho de Melo) - Show group details on the title line in the annotate browser and 'perf annotate --stdio2' output, so that the per-event columns can have headers (Arnaldo Carvalho de Melo) - Fixup vertical line separating metrics from instructions and cleaning unused lines at the bottom, both in the annotate TUI browser (Arnaldo Carvalho de Melo) - Remove duplicated 'samples' in lost samples warning in 'perf report' (Arnaldo Carvalho de Melo) - Synchronize i915_drm.h, silencing the perf build process, automagically adding support for the new DRM_I915_QUERY ioctl (Arnaldo Carvalho de Melo) - Make auxtrace_queues__add_buffer() allocate struct buffer, from a patchkit already applied (Adrian Hunter) - Fix the --stdio2/TUI annotate output to include group details, be it for a recorded '{a,b,f}' explicit event group or when forcing group display using 'perf report --group' for a set of events not recorded as a group (Arnaldo Carvalho de Melo) - Fix display artifacts in the ui browser (base class for the annotate and main report/top TUI browser) related to the extra title lines work (Arnaldo Carvalho de Melo) - perf auxtrace refactorings, leftovers from a previously partially processed patchset (Adrian Hunter) - Fix the builtin clang build (Sandipan Das, Arnaldo Carvalho de Melo) - Synchronize i915_drm.h, silencing a perf build warning and in the process automagically adding support for a new ioctl command (Arnaldo Carvalho de Melo) - Fix a strncpy issue in uprobe tracing" * 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (36 commits) perf/core: Need CAP_SYS_ADMIN to create k/uprobe with perf_event_open() tracing/uprobe_event: Fix strncpy corner case perf/core: Fix perf_uprobe_init() perf/core: Fix perf_kprobe_init() perf/core: Fix use-after-free in uprobe_perf_close() perf tests clang: Fix function name for clang IR test perf clang: Add support for recent clang versions perf tools: Fix perf builds with clang support perf tools: No need to include namespaces.h in util.h perf hists browser: Remove leftover from row returned from refresh perf hists browser: Show extra_title_lines in the 'D' debug hotkey perf auxtrace: Make auxtrace_queues__add_buffer() do CPU filtering tools headers uapi: Synchronize i915_drm.h perf report: Remove duplicated 'samples' in lost samples warning perf ui browser: Fixup cleaning unused lines at the bottom perf annotate browser: Fixup vertical line separating metrics from instructions perf annotate: Show group details on the title line perf auxtrace: Make auxtrace_queues__add_buffer() allocate struct buffer perf/x86/intel: Move regs->flags EXACT bit init perf trace: Remove redundant ')' ...
-rw-r--r--arch/x86/events/intel/ds.c34
-rw-r--r--kernel/events/core.c14
-rw-r--r--kernel/trace/trace_event_perf.c4
-rw-r--r--kernel/trace/trace_uprobe.c2
-rw-r--r--tools/arch/x86/include/asm/cpufeatures.h2
-rw-r--r--tools/include/tools/config.h34
-rw-r--r--tools/include/uapi/drm/i915_drm.h112
-rw-r--r--tools/perf/Documentation/perf-report.txt1
-rw-r--r--tools/perf/Documentation/perf-trace.txt3
-rw-r--r--tools/perf/Documentation/perf-version.txt24
-rw-r--r--tools/perf/Makefile.config8
-rw-r--r--tools/perf/Makefile.perf3
-rw-r--r--tools/perf/builtin-trace.c11
-rw-r--r--tools/perf/builtin-version.c82
-rw-r--r--tools/perf/perf.c6
-rw-r--r--tools/perf/perf.h1
-rw-r--r--tools/perf/ui/browser.c12
-rw-r--r--tools/perf/ui/browser.h2
-rw-r--r--tools/perf/ui/browsers/annotate.c33
-rw-r--r--tools/perf/ui/browsers/hists.c138
-rw-r--r--tools/perf/util/annotate.c51
-rw-r--r--tools/perf/util/annotate.h12
-rw-r--r--tools/perf/util/auxtrace.c72
-rw-r--r--tools/perf/util/c++/clang-test.cpp2
-rw-r--r--tools/perf/util/c++/clang.cpp11
-rw-r--r--tools/perf/util/dwarf-aux.c2
-rw-r--r--tools/perf/util/hist.c81
-rw-r--r--tools/perf/util/hist.h7
-rw-r--r--tools/perf/util/map.h4
-rw-r--r--tools/perf/util/session.c2
-rw-r--r--tools/perf/util/sort.c41
-rw-r--r--tools/perf/util/sort.h1
-rw-r--r--tools/perf/util/util.h4
33 files changed, 629 insertions, 187 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,
1153 if (pebs == NULL) 1153 if (pebs == NULL)
1154 return; 1154 return;
1155 1155
1156 regs->flags &= ~PERF_EFLAGS_EXACT;
1157 sample_type = event->attr.sample_type; 1156 sample_type = event->attr.sample_type;
1158 dsrc = sample_type & PERF_SAMPLE_DATA_SRC; 1157 dsrc = sample_type & PERF_SAMPLE_DATA_SRC;
1159 1158
@@ -1197,7 +1196,13 @@ static void setup_pebs_sample_data(struct perf_event *event,
1197 * and PMI. 1196 * and PMI.
1198 */ 1197 */
1199 *regs = *iregs; 1198 *regs = *iregs;
1200 regs->flags = pebs->flags; 1199
1200 /*
1201 * Initialize regs_>flags from PEBS,
1202 * Clear exact bit (which uses x86 EFLAGS Reserved bit 3),
1203 * i.e., do not rely on it being zero:
1204 */
1205 regs->flags = pebs->flags & ~PERF_EFLAGS_EXACT;
1201 1206
1202 if (sample_type & PERF_SAMPLE_REGS_INTR) { 1207 if (sample_type & PERF_SAMPLE_REGS_INTR) {
1203 regs->ax = pebs->ax; 1208 regs->ax = pebs->ax;
@@ -1217,10 +1222,6 @@ static void setup_pebs_sample_data(struct perf_event *event,
1217 regs->sp = pebs->sp; 1222 regs->sp = pebs->sp;
1218 } 1223 }
1219 1224
1220 /*
1221 * Preserve PERF_EFLAGS_VM from set_linear_ip().
1222 */
1223 regs->flags = pebs->flags | (regs->flags & PERF_EFLAGS_VM);
1224#ifndef CONFIG_X86_32 1225#ifndef CONFIG_X86_32
1225 regs->r8 = pebs->r8; 1226 regs->r8 = pebs->r8;
1226 regs->r9 = pebs->r9; 1227 regs->r9 = pebs->r9;
@@ -1234,20 +1235,33 @@ static void setup_pebs_sample_data(struct perf_event *event,
1234 } 1235 }
1235 1236
1236 if (event->attr.precise_ip > 1) { 1237 if (event->attr.precise_ip > 1) {
1237 /* Haswell and later have the eventing IP, so use it: */ 1238 /*
1239 * Haswell and later processors have an 'eventing IP'
1240 * (real IP) which fixes the off-by-1 skid in hardware.
1241 * Use it when precise_ip >= 2 :
1242 */
1238 if (x86_pmu.intel_cap.pebs_format >= 2) { 1243 if (x86_pmu.intel_cap.pebs_format >= 2) {
1239 set_linear_ip(regs, pebs->real_ip); 1244 set_linear_ip(regs, pebs->real_ip);
1240 regs->flags |= PERF_EFLAGS_EXACT; 1245 regs->flags |= PERF_EFLAGS_EXACT;
1241 } else { 1246 } else {
1242 /* Otherwise use PEBS off-by-1 IP: */ 1247 /* Otherwise, use PEBS off-by-1 IP: */
1243 set_linear_ip(regs, pebs->ip); 1248 set_linear_ip(regs, pebs->ip);
1244 1249
1245 /* ... and try to fix it up using the LBR entries: */ 1250 /*
1251 * With precise_ip >= 2, try to fix up the off-by-1 IP
1252 * using the LBR. If successful, the fixup function
1253 * corrects regs->ip and calls set_linear_ip() on regs:
1254 */
1246 if (intel_pmu_pebs_fixup_ip(regs)) 1255 if (intel_pmu_pebs_fixup_ip(regs))
1247 regs->flags |= PERF_EFLAGS_EXACT; 1256 regs->flags |= PERF_EFLAGS_EXACT;
1248 } 1257 }
1249 } else 1258 } else {
1259 /*
1260 * When precise_ip == 1, return the PEBS off-by-1 IP,
1261 * no fixup attempted:
1262 */
1250 set_linear_ip(regs, pebs->ip); 1263 set_linear_ip(regs, pebs->ip);
1264 }
1251 1265
1252 1266
1253 if ((sample_type & (PERF_SAMPLE_ADDR | PERF_SAMPLE_PHYS_ADDR)) && 1267 if ((sample_type & (PERF_SAMPLE_ADDR | PERF_SAMPLE_PHYS_ADDR)) &&
diff --git a/kernel/events/core.c b/kernel/events/core.c
index fc1c330c6bd6..2d5fe26551f8 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -4447,6 +4447,9 @@ static void _free_event(struct perf_event *event)
4447 if (event->ctx) 4447 if (event->ctx)
4448 put_ctx(event->ctx); 4448 put_ctx(event->ctx);
4449 4449
4450 if (event->hw.target)
4451 put_task_struct(event->hw.target);
4452
4450 exclusive_event_destroy(event); 4453 exclusive_event_destroy(event);
4451 module_put(event->pmu->module); 4454 module_put(event->pmu->module);
4452 4455
@@ -8397,6 +8400,10 @@ static int perf_kprobe_event_init(struct perf_event *event)
8397 8400
8398 if (event->attr.type != perf_kprobe.type) 8401 if (event->attr.type != perf_kprobe.type)
8399 return -ENOENT; 8402 return -ENOENT;
8403
8404 if (!capable(CAP_SYS_ADMIN))
8405 return -EACCES;
8406
8400 /* 8407 /*
8401 * no branch sampling for probe events 8408 * no branch sampling for probe events
8402 */ 8409 */
@@ -8434,6 +8441,10 @@ static int perf_uprobe_event_init(struct perf_event *event)
8434 8441
8435 if (event->attr.type != perf_uprobe.type) 8442 if (event->attr.type != perf_uprobe.type)
8436 return -ENOENT; 8443 return -ENOENT;
8444
8445 if (!capable(CAP_SYS_ADMIN))
8446 return -EACCES;
8447
8437 /* 8448 /*
8438 * no branch sampling for probe events 8449 * no branch sampling for probe events
8439 */ 8450 */
@@ -9955,6 +9966,7 @@ perf_event_alloc(struct perf_event_attr *attr, int cpu,
9955 * and we cannot use the ctx information because we need the 9966 * and we cannot use the ctx information because we need the
9956 * pmu before we get a ctx. 9967 * pmu before we get a ctx.
9957 */ 9968 */
9969 get_task_struct(task);
9958 event->hw.target = task; 9970 event->hw.target = task;
9959 } 9971 }
9960 9972
@@ -10070,6 +10082,8 @@ err_ns:
10070 perf_detach_cgroup(event); 10082 perf_detach_cgroup(event);
10071 if (event->ns) 10083 if (event->ns)
10072 put_pid_ns(event->ns); 10084 put_pid_ns(event->ns);
10085 if (event->hw.target)
10086 put_task_struct(event->hw.target);
10073 kfree(event); 10087 kfree(event);
10074 10088
10075 return ERR_PTR(err); 10089 return ERR_PTR(err);
diff --git a/kernel/trace/trace_event_perf.c b/kernel/trace/trace_event_perf.c
index 2c416509b834..c79193e598f5 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)
252 ret = strncpy_from_user( 252 ret = strncpy_from_user(
253 func, u64_to_user_ptr(p_event->attr.kprobe_func), 253 func, u64_to_user_ptr(p_event->attr.kprobe_func),
254 KSYM_NAME_LEN); 254 KSYM_NAME_LEN);
255 if (ret == KSYM_NAME_LEN)
256 ret = -E2BIG;
255 if (ret < 0) 257 if (ret < 0)
256 goto out; 258 goto out;
257 259
@@ -300,6 +302,8 @@ int perf_uprobe_init(struct perf_event *p_event, bool is_retprobe)
300 return -ENOMEM; 302 return -ENOMEM;
301 ret = strncpy_from_user( 303 ret = strncpy_from_user(
302 path, u64_to_user_ptr(p_event->attr.uprobe_path), PATH_MAX); 304 path, u64_to_user_ptr(p_event->attr.uprobe_path), PATH_MAX);
305 if (ret == PATH_MAX)
306 return -E2BIG;
303 if (ret < 0) 307 if (ret < 0)
304 goto out; 308 goto out;
305 if (path[0] == '\0') { 309 if (path[0] == '\0') {
diff --git a/kernel/trace/trace_uprobe.c b/kernel/trace/trace_uprobe.c
index 469ba7ecd14b..34fd0e0ec51d 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,
151 return; 151 return;
152 152
153 ret = strncpy_from_user(dst, src, maxlen); 153 ret = strncpy_from_user(dst, src, maxlen);
154 if (ret == maxlen)
155 dst[--ret] = '\0';
154 156
155 if (ret < 0) { /* Failed to fetch string */ 157 if (ret < 0) { /* Failed to fetch string */
156 ((u8 *)get_rloc_data(dest))[0] = '\0'; 158 ((u8 *)get_rloc_data(dest))[0] = '\0';
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 @@
316#define X86_FEATURE_VPCLMULQDQ (16*32+10) /* Carry-Less Multiplication Double Quadword */ 316#define X86_FEATURE_VPCLMULQDQ (16*32+10) /* Carry-Less Multiplication Double Quadword */
317#define X86_FEATURE_AVX512_VNNI (16*32+11) /* Vector Neural Network Instructions */ 317#define X86_FEATURE_AVX512_VNNI (16*32+11) /* Vector Neural Network Instructions */
318#define X86_FEATURE_AVX512_BITALG (16*32+12) /* Support for VPOPCNT[B,W] and VPSHUF-BITQMB instructions */ 318#define X86_FEATURE_AVX512_BITALG (16*32+12) /* Support for VPOPCNT[B,W] and VPSHUF-BITQMB instructions */
319#define X86_FEATURE_TME (16*32+13) /* Intel Total Memory Encryption */
319#define X86_FEATURE_AVX512_VPOPCNTDQ (16*32+14) /* POPCNT for vectors of DW/QW */ 320#define X86_FEATURE_AVX512_VPOPCNTDQ (16*32+14) /* POPCNT for vectors of DW/QW */
320#define X86_FEATURE_LA57 (16*32+16) /* 5-level page tables */ 321#define X86_FEATURE_LA57 (16*32+16) /* 5-level page tables */
321#define X86_FEATURE_RDPID (16*32+22) /* RDPID instruction */ 322#define X86_FEATURE_RDPID (16*32+22) /* RDPID instruction */
@@ -328,6 +329,7 @@
328/* Intel-defined CPU features, CPUID level 0x00000007:0 (EDX), word 18 */ 329/* Intel-defined CPU features, CPUID level 0x00000007:0 (EDX), word 18 */
329#define X86_FEATURE_AVX512_4VNNIW (18*32+ 2) /* AVX-512 Neural Network Instructions */ 330#define X86_FEATURE_AVX512_4VNNIW (18*32+ 2) /* AVX-512 Neural Network Instructions */
330#define X86_FEATURE_AVX512_4FMAPS (18*32+ 3) /* AVX-512 Multiply Accumulation Single precision */ 331#define X86_FEATURE_AVX512_4FMAPS (18*32+ 3) /* AVX-512 Multiply Accumulation Single precision */
332#define X86_FEATURE_PCONFIG (18*32+18) /* Intel PCONFIG */
331#define X86_FEATURE_SPEC_CTRL (18*32+26) /* "" Speculation Control (IBRS + IBPB) */ 333#define X86_FEATURE_SPEC_CTRL (18*32+26) /* "" Speculation Control (IBRS + IBPB) */
332#define X86_FEATURE_INTEL_STIBP (18*32+27) /* "" Single Thread Indirect Branch Predictors */ 334#define X86_FEATURE_INTEL_STIBP (18*32+27) /* "" Single Thread Indirect Branch Predictors */
333#define X86_FEATURE_ARCH_CAPABILITIES (18*32+29) /* IA32_ARCH_CAPABILITIES MSR (Intel) */ 335#define X86_FEATURE_ARCH_CAPABILITIES (18*32+29) /* IA32_ARCH_CAPABILITIES MSR (Intel) */
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 @@
1/* SPDX-License-Identifier: GPL-2.0 */
2#ifndef _TOOLS_CONFIG_H
3#define _TOOLS_CONFIG_H
4
5/* Subset of include/linux/kconfig.h */
6
7#define __ARG_PLACEHOLDER_1 0,
8#define __take_second_arg(__ignored, val, ...) val
9
10/*
11 * Helper macros to use CONFIG_ options in C/CPP expressions. Note that
12 * these only work with boolean and tristate options.
13 */
14
15/*
16 * Getting something that works in C and CPP for an arg that may or may
17 * not be defined is tricky. Here, if we have "#define CONFIG_BOOGER 1"
18 * we match on the placeholder define, insert the "0," for arg1 and generate
19 * the triplet (0, 1, 0). Then the last step cherry picks the 2nd arg (a one).
20 * When CONFIG_BOOGER is not defined, we generate a (... 1, 0) pair, and when
21 * the last step cherry picks the 2nd arg, we get a zero.
22 */
23#define __is_defined(x) ___is_defined(x)
24#define ___is_defined(val) ____is_defined(__ARG_PLACEHOLDER_##val)
25#define ____is_defined(arg1_or_junk) __take_second_arg(arg1_or_junk 1, 0)
26
27/*
28 * IS_BUILTIN(CONFIG_FOO) evaluates to 1 if CONFIG_FOO is set to 'y', 0
29 * otherwise. For boolean options, this is equivalent to
30 * IS_ENABLED(CONFIG_FOO).
31 */
32#define IS_BUILTIN(option) __is_defined(option)
33
34#endif /* _TOOLS_CONFIG_H */
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 {
318#define DRM_I915_PERF_OPEN 0x36 318#define DRM_I915_PERF_OPEN 0x36
319#define DRM_I915_PERF_ADD_CONFIG 0x37 319#define DRM_I915_PERF_ADD_CONFIG 0x37
320#define DRM_I915_PERF_REMOVE_CONFIG 0x38 320#define DRM_I915_PERF_REMOVE_CONFIG 0x38
321#define DRM_I915_QUERY 0x39
321 322
322#define DRM_IOCTL_I915_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t) 323#define DRM_IOCTL_I915_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t)
323#define DRM_IOCTL_I915_FLUSH DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLUSH) 324#define DRM_IOCTL_I915_FLUSH DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLUSH)
@@ -375,6 +376,7 @@ typedef struct _drm_i915_sarea {
375#define DRM_IOCTL_I915_PERF_OPEN DRM_IOW(DRM_COMMAND_BASE + DRM_I915_PERF_OPEN, struct drm_i915_perf_open_param) 376#define DRM_IOCTL_I915_PERF_OPEN DRM_IOW(DRM_COMMAND_BASE + DRM_I915_PERF_OPEN, struct drm_i915_perf_open_param)
376#define DRM_IOCTL_I915_PERF_ADD_CONFIG DRM_IOW(DRM_COMMAND_BASE + DRM_I915_PERF_ADD_CONFIG, struct drm_i915_perf_oa_config) 377#define DRM_IOCTL_I915_PERF_ADD_CONFIG DRM_IOW(DRM_COMMAND_BASE + DRM_I915_PERF_ADD_CONFIG, struct drm_i915_perf_oa_config)
377#define DRM_IOCTL_I915_PERF_REMOVE_CONFIG DRM_IOW(DRM_COMMAND_BASE + DRM_I915_PERF_REMOVE_CONFIG, __u64) 378#define DRM_IOCTL_I915_PERF_REMOVE_CONFIG DRM_IOW(DRM_COMMAND_BASE + DRM_I915_PERF_REMOVE_CONFIG, __u64)
379#define DRM_IOCTL_I915_QUERY DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_QUERY, struct drm_i915_query)
378 380
379/* Allow drivers to submit batchbuffers directly to hardware, relying 381/* Allow drivers to submit batchbuffers directly to hardware, relying
380 * on the security mechanisms provided by hardware. 382 * on the security mechanisms provided by hardware.
@@ -1358,7 +1360,9 @@ struct drm_intel_overlay_attrs {
1358 * active on a given plane. 1360 * active on a given plane.
1359 */ 1361 */
1360 1362
1361#define I915_SET_COLORKEY_NONE (1<<0) /* disable color key matching */ 1363#define I915_SET_COLORKEY_NONE (1<<0) /* Deprecated. Instead set
1364 * flags==0 to disable colorkeying.
1365 */
1362#define I915_SET_COLORKEY_DESTINATION (1<<1) 1366#define I915_SET_COLORKEY_DESTINATION (1<<1)
1363#define I915_SET_COLORKEY_SOURCE (1<<2) 1367#define I915_SET_COLORKEY_SOURCE (1<<2)
1364struct drm_intel_sprite_colorkey { 1368struct drm_intel_sprite_colorkey {
@@ -1604,15 +1608,115 @@ struct drm_i915_perf_oa_config {
1604 __u32 n_flex_regs; 1608 __u32 n_flex_regs;
1605 1609
1606 /* 1610 /*
1607 * These fields are pointers to tuples of u32 values (register 1611 * These fields are pointers to tuples of u32 values (register address,
1608 * address, value). For example the expected length of the buffer 1612 * value). For example the expected length of the buffer pointed by
1609 * pointed by mux_regs_ptr is (2 * sizeof(u32) * n_mux_regs). 1613 * mux_regs_ptr is (2 * sizeof(u32) * n_mux_regs).
1610 */ 1614 */
1611 __u64 mux_regs_ptr; 1615 __u64 mux_regs_ptr;
1612 __u64 boolean_regs_ptr; 1616 __u64 boolean_regs_ptr;
1613 __u64 flex_regs_ptr; 1617 __u64 flex_regs_ptr;
1614}; 1618};
1615 1619
1620struct drm_i915_query_item {
1621 __u64 query_id;
1622#define DRM_I915_QUERY_TOPOLOGY_INFO 1
1623
1624 /*
1625 * When set to zero by userspace, this is filled with the size of the
1626 * data to be written at the data_ptr pointer. The kernel sets this
1627 * value to a negative value to signal an error on a particular query
1628 * item.
1629 */
1630 __s32 length;
1631
1632 /*
1633 * Unused for now. Must be cleared to zero.
1634 */
1635 __u32 flags;
1636
1637 /*
1638 * Data will be written at the location pointed by data_ptr when the
1639 * value of length matches the length of the data to be written by the
1640 * kernel.
1641 */
1642 __u64 data_ptr;
1643};
1644
1645struct drm_i915_query {
1646 __u32 num_items;
1647
1648 /*
1649 * Unused for now. Must be cleared to zero.
1650 */
1651 __u32 flags;
1652
1653 /*
1654 * This points to an array of num_items drm_i915_query_item structures.
1655 */
1656 __u64 items_ptr;
1657};
1658
1659/*
1660 * Data written by the kernel with query DRM_I915_QUERY_TOPOLOGY_INFO :
1661 *
1662 * data: contains the 3 pieces of information :
1663 *
1664 * - the slice mask with one bit per slice telling whether a slice is
1665 * available. The availability of slice X can be queried with the following
1666 * formula :
1667 *
1668 * (data[X / 8] >> (X % 8)) & 1
1669 *
1670 * - the subslice mask for each slice with one bit per subslice telling
1671 * whether a subslice is available. The availability of subslice Y in slice
1672 * X can be queried with the following formula :
1673 *
1674 * (data[subslice_offset +
1675 * X * subslice_stride +
1676 * Y / 8] >> (Y % 8)) & 1
1677 *
1678 * - the EU mask for each subslice in each slice with one bit per EU telling
1679 * whether an EU is available. The availability of EU Z in subslice Y in
1680 * slice X can be queried with the following formula :
1681 *
1682 * (data[eu_offset +
1683 * (X * max_subslices + Y) * eu_stride +
1684 * Z / 8] >> (Z % 8)) & 1
1685 */
1686struct drm_i915_query_topology_info {
1687 /*
1688 * Unused for now. Must be cleared to zero.
1689 */
1690 __u16 flags;
1691
1692 __u16 max_slices;
1693 __u16 max_subslices;
1694 __u16 max_eus_per_subslice;
1695
1696 /*
1697 * Offset in data[] at which the subslice masks are stored.
1698 */
1699 __u16 subslice_offset;
1700
1701 /*
1702 * Stride at which each of the subslice masks for each slice are
1703 * stored.
1704 */
1705 __u16 subslice_stride;
1706
1707 /*
1708 * Offset in data[] at which the EU masks are stored.
1709 */
1710 __u16 eu_offset;
1711
1712 /*
1713 * Stride at which each of the EU masks for each subslice are stored.
1714 */
1715 __u16 eu_stride;
1716
1717 __u8 data[];
1718};
1719
1616#if defined(__cplusplus) 1720#if defined(__cplusplus)
1617} 1721}
1618#endif 1722#endif
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
80 - comm: command (name) of the task which can be read via /proc/<pid>/comm 80 - comm: command (name) of the task which can be read via /proc/<pid>/comm
81 - pid: command and tid of the task 81 - pid: command and tid of the task
82 - dso: name of library or module executed at the time of sample 82 - dso: name of library or module executed at the time of sample
83 - dso_size: size of library or module executed at the time of sample
83 - symbol: name of function executed at the time of sample 84 - symbol: name of function executed at the time of sample
84 - symbol_size: size of function executed at the time of sample 85 - symbol_size: size of function executed at the time of sample
85 - parent: name of function matched to the parent regex filter. Unmatched 86 - parent: name of function matched to the parent regex filter. Unmatched
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.
117--sched:: 117--sched::
118 Accrue thread runtime and provide a summary at the end of the session. 118 Accrue thread runtime and provide a summary at the end of the session.
119 119
120--failure::
121 Show only syscalls that failed, i.e. that returned < 0.
122
120-i:: 123-i::
121--input:: 124--input::
122 Process events from a given perf data file. 125 Process events from a given perf data file.
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 @@
1perf-version(1)
2===============
3
4NAME
5----
6perf-version - display the version of perf binary
7
8SYNOPSIS
9--------
10'perf version' [--build-options]
11
12DESCRIPTION
13-----------
14With no options given, the 'perf version' prints the perf version
15on the standard output.
16
17If the option '--build-options' is given, then the status of
18compiled-in libraries are printed on the standard output.
19
20OPTIONS
21-------
22--build-options::
23 Prints the status of compiled-in libraries on the
24 standard output.
diff --git a/tools/perf/Makefile.config b/tools/perf/Makefile.config
index 98ff73648b51..c7abd83a8e19 100644
--- a/tools/perf/Makefile.config
+++ b/tools/perf/Makefile.config
@@ -346,12 +346,16 @@ else
346 ifneq ($(feature-dwarf_getlocations), 1) 346 ifneq ($(feature-dwarf_getlocations), 1)
347 msg := $(warning Old libdw.h, finding variables at given 'perf probe' point will not work, install elfutils-devel/libdw-dev >= 0.157); 347 msg := $(warning Old libdw.h, finding variables at given 'perf probe' point will not work, install elfutils-devel/libdw-dev >= 0.157);
348 else 348 else
349 CFLAGS += -DHAVE_DWARF_GETLOCATIONS 349 CFLAGS += -DHAVE_DWARF_GETLOCATIONS_SUPPORT
350 endif # dwarf_getlocations 350 endif # dwarf_getlocations
351 endif # Dwarf support 351 endif # Dwarf support
352 endif # libelf support 352 endif # libelf support
353endif # NO_LIBELF 353endif # NO_LIBELF
354 354
355ifeq ($(feature-glibc), 1)
356 CFLAGS += -DHAVE_GLIBC_SUPPORT
357endif
358
355ifdef NO_DWARF 359ifdef NO_DWARF
356 NO_LIBDW_DWARF_UNWIND := 1 360 NO_LIBDW_DWARF_UNWIND := 1
357endif 361endif
@@ -635,6 +639,7 @@ else
635 else 639 else
636 LDFLAGS += $(PERL_EMBED_LDFLAGS) 640 LDFLAGS += $(PERL_EMBED_LDFLAGS)
637 EXTLIBS += $(PERL_EMBED_LIBADD) 641 EXTLIBS += $(PERL_EMBED_LIBADD)
642 CFLAGS += -DHAVE_LIBPERL_SUPPORT
638 $(call detected,CONFIG_LIBPERL) 643 $(call detected,CONFIG_LIBPERL)
639 endif 644 endif
640endif 645endif
@@ -671,6 +676,7 @@ else
671 LDFLAGS += $(PYTHON_EMBED_LDFLAGS) 676 LDFLAGS += $(PYTHON_EMBED_LDFLAGS)
672 EXTLIBS += $(PYTHON_EMBED_LIBADD) 677 EXTLIBS += $(PYTHON_EMBED_LIBADD)
673 LANG_BINDINGS += $(obj-perf)python/perf.so 678 LANG_BINDINGS += $(obj-perf)python/perf.so
679 CFLAGS += -DHAVE_LIBPYTHON_SUPPORT
674 $(call detected,CONFIG_LIBPYTHON) 680 $(call detected,CONFIG_LIBPYTHON)
675 endif 681 endif
676 endif 682 endif
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
364 364
365ifeq ($(USE_CLANG), 1) 365ifeq ($(USE_CLANG), 1)
366 CLANGLIBS_LIST = AST Basic CodeGen Driver Frontend Lex Tooling Edit Sema Analysis Parse Serialization 366 CLANGLIBS_LIST = AST Basic CodeGen Driver Frontend Lex Tooling Edit Sema Analysis Parse Serialization
367 LIBCLANG = $(foreach l,$(CLANGLIBS_LIST),$(wildcard $(shell $(LLVM_CONFIG) --libdir)/libclang$(l).a)) 367 CLANGLIBS_NOEXT_LIST = $(foreach l,$(CLANGLIBS_LIST),$(shell $(LLVM_CONFIG) --libdir)/libclang$(l))
368 LIBCLANG = $(foreach l,$(CLANGLIBS_NOEXT_LIST),$(wildcard $(l).a $(l).so))
368 LIBS += -Wl,--start-group $(LIBCLANG) -Wl,--end-group 369 LIBS += -Wl,--start-group $(LIBCLANG) -Wl,--end-group
369endif 370endif
370 371
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index 87b95c9410b4..3ad17ee89403 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -112,6 +112,7 @@ struct trace {
112 bool multiple_threads; 112 bool multiple_threads;
113 bool summary; 113 bool summary;
114 bool summary_only; 114 bool summary_only;
115 bool failure_only;
115 bool show_comm; 116 bool show_comm;
116 bool print_sample; 117 bool print_sample;
117 bool show_tool_stats; 118 bool show_tool_stats;
@@ -1565,7 +1566,7 @@ static int trace__printf_interrupted_entry(struct trace *trace)
1565 struct thread_trace *ttrace; 1566 struct thread_trace *ttrace;
1566 size_t printed; 1567 size_t printed;
1567 1568
1568 if (trace->current == NULL) 1569 if (trace->failure_only || trace->current == NULL)
1569 return 0; 1570 return 0;
1570 1571
1571 ttrace = thread__priv(trace->current); 1572 ttrace = thread__priv(trace->current);
@@ -1638,7 +1639,7 @@ static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel,
1638 args, trace, thread); 1639 args, trace, thread);
1639 1640
1640 if (sc->is_exit) { 1641 if (sc->is_exit) {
1641 if (!(trace->duration_filter || trace->summary_only || trace->min_stack)) { 1642 if (!(trace->duration_filter || trace->summary_only || trace->failure_only || trace->min_stack)) {
1642 trace__fprintf_entry_head(trace, thread, 0, false, ttrace->entry_time, trace->output); 1643 trace__fprintf_entry_head(trace, thread, 0, false, ttrace->entry_time, trace->output);
1643 fprintf(trace->output, "%-70s)\n", ttrace->entry_str); 1644 fprintf(trace->output, "%-70s)\n", ttrace->entry_str);
1644 } 1645 }
@@ -1742,7 +1743,7 @@ static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel,
1742 } 1743 }
1743 } 1744 }
1744 1745
1745 if (trace->summary_only) 1746 if (trace->summary_only || (ret >= 0 && trace->failure_only))
1746 goto out; 1747 goto out;
1747 1748
1748 trace__fprintf_entry_head(trace, thread, duration, duration_calculated, ttrace->entry_time, trace->output); 1749 trace__fprintf_entry_head(trace, thread, duration, duration_calculated, ttrace->entry_time, trace->output);
@@ -1961,7 +1962,7 @@ static int trace__event_handler(struct trace *trace, struct perf_evsel *evsel,
1961 trace->output); 1962 trace->output);
1962 } 1963 }
1963 1964
1964 fprintf(trace->output, ")\n"); 1965 fprintf(trace->output, "\n");
1965 1966
1966 if (callchain_ret > 0) 1967 if (callchain_ret > 0)
1967 trace__fprintf_callchain(trace, sample); 1968 trace__fprintf_callchain(trace, sample);
@@ -3087,6 +3088,8 @@ int cmd_trace(int argc, const char **argv)
3087 OPT_INCR('v', "verbose", &verbose, "be more verbose"), 3088 OPT_INCR('v', "verbose", &verbose, "be more verbose"),
3088 OPT_BOOLEAN('T', "time", &trace.full_time, 3089 OPT_BOOLEAN('T', "time", &trace.full_time,
3089 "Show full timestamp, not time relative to first start"), 3090 "Show full timestamp, not time relative to first start"),
3091 OPT_BOOLEAN(0, "failure", &trace.failure_only,
3092 "Show only syscalls that failed"),
3090 OPT_BOOLEAN('s', "summary", &trace.summary_only, 3093 OPT_BOOLEAN('s', "summary", &trace.summary_only,
3091 "Show only syscall summary with statistics"), 3094 "Show only syscall summary with statistics"),
3092 OPT_BOOLEAN('S', "with-summary", &trace.summary, 3095 OPT_BOOLEAN('S', "with-summary", &trace.summary,
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 @@
1// SPDX-License-Identifier: GPL-2.0 1// SPDX-License-Identifier: GPL-2.0
2#include "builtin.h" 2#include "builtin.h"
3#include "perf.h" 3#include "perf.h"
4#include "color.h"
4#include <linux/compiler.h> 5#include <linux/compiler.h>
6#include <tools/config.h>
5#include <stdio.h> 7#include <stdio.h>
8#include <string.h>
9#include <subcmd/parse-options.h>
6 10
7int cmd_version(int argc __maybe_unused, const char **argv __maybe_unused) 11int version_verbose;
12
13struct version {
14 bool build_options;
15};
16
17static struct version version;
18
19static struct option version_options[] = {
20 OPT_BOOLEAN(0, "build-options", &version.build_options,
21 "display the build options"),
22};
23
24static const char * const version_usage[] = {
25 "perf version [<options>]",
26 NULL
27};
28
29static void on_off_print(const char *status)
30{
31 printf("[ ");
32
33 if (!strcmp(status, "OFF"))
34 color_fprintf(stdout, PERF_COLOR_RED, "%-3s", status);
35 else
36 color_fprintf(stdout, PERF_COLOR_GREEN, "%-3s", status);
37
38 printf(" ]");
39}
40
41static void status_print(const char *name, const char *macro,
42 const char *status)
8{ 43{
44 printf("%22s: ", name);
45 on_off_print(status);
46 printf(" # %s\n", macro);
47}
48
49#define STATUS(__d, __m) \
50do { \
51 if (IS_BUILTIN(__d)) \
52 status_print(#__m, #__d, "on"); \
53 else \
54 status_print(#__m, #__d, "OFF"); \
55} while (0)
56
57static void library_status(void)
58{
59 STATUS(HAVE_DWARF_SUPPORT, dwarf);
60 STATUS(HAVE_DWARF_GETLOCATIONS_SUPPORT, dwarf_getlocations);
61 STATUS(HAVE_GLIBC_SUPPORT, glibc);
62 STATUS(HAVE_GTK2_SUPPORT, gtk2);
63 STATUS(HAVE_LIBAUDIT_SUPPORT, libaudit);
64 STATUS(HAVE_LIBBFD_SUPPORT, libbfd);
65 STATUS(HAVE_LIBELF_SUPPORT, libelf);
66 STATUS(HAVE_LIBNUMA_SUPPORT, libnuma);
67 STATUS(HAVE_LIBNUMA_SUPPORT, numa_num_possible_cpus);
68 STATUS(HAVE_LIBPERL_SUPPORT, libperl);
69 STATUS(HAVE_LIBPYTHON_SUPPORT, libpython);
70 STATUS(HAVE_SLANG_SUPPORT, libslang);
71 STATUS(HAVE_LIBCRYPTO_SUPPORT, libcrypto);
72 STATUS(HAVE_LIBUNWIND_SUPPORT, libunwind);
73 STATUS(HAVE_DWARF_SUPPORT, libdw-dwarf-unwind);
74 STATUS(HAVE_ZLIB_SUPPORT, zlib);
75 STATUS(HAVE_LZMA_SUPPORT, lzma);
76 STATUS(HAVE_AUXTRACE_SUPPORT, get_cpuid);
77 STATUS(HAVE_LIBBPF_SUPPORT, bpf);
78}
79
80int cmd_version(int argc, const char **argv)
81{
82 argc = parse_options(argc, argv, version_options, version_usage,
83 PARSE_OPT_STOP_AT_NON_OPTION);
84
9 printf("perf version %s\n", perf_version_string); 85 printf("perf version %s\n", perf_version_string);
86
87 if (version.build_options || version_verbose == 1)
88 library_status();
89
10 return 0; 90 return 0;
11} 91}
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)
190 break; 190 break;
191 } 191 }
192 192
193 if (!strcmp(cmd, "-vv")) {
194 (*argv)[0] = "version";
195 version_verbose = 1;
196 break;
197 }
198
193 /* 199 /*
194 * Check remaining flags. 200 * Check remaining flags.
195 */ 201 */
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 {
84struct option; 84struct option;
85extern const char * const *record_usage; 85extern const char * const *record_usage;
86extern struct option *record_options; 86extern struct option *record_options;
87extern int version_verbose;
87 88
88int record__parse_freq(const struct option *opt, const char *str, int unset); 89int record__parse_freq(const struct option *opt, const char *str, int unset);
89#endif 90#endif
diff --git a/tools/perf/ui/browser.c b/tools/perf/ui/browser.c
index 9f6ce29b83b4..4f75561424ed 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,
45 ui_browser__set_color(browser, color); 45 ui_browser__set_color(browser, color);
46} 46}
47 47
48void ui_browser__gotorc(struct ui_browser *browser, int y, int x) 48void ui_browser__gotorc_title(struct ui_browser *browser, int y, int x)
49{ 49{
50 SLsmg_gotorc(browser->y + y, browser->x + x); 50 SLsmg_gotorc(browser->y + y, browser->x + x);
51} 51}
52 52
53void ui_browser__gotorc(struct ui_browser *browser, int y, int x)
54{
55 SLsmg_gotorc(browser->y + y + browser->extra_title_lines, browser->x + x);
56}
57
53void ui_browser__write_nstring(struct ui_browser *browser __maybe_unused, const char *msg, 58void ui_browser__write_nstring(struct ui_browser *browser __maybe_unused, const char *msg,
54 unsigned int width) 59 unsigned int width)
55{ 60{
@@ -191,6 +196,7 @@ void ui_browser__refresh_dimensions(struct ui_browser *browser)
191{ 196{
192 browser->width = SLtt_Screen_Cols - 1; 197 browser->width = SLtt_Screen_Cols - 1;
193 browser->height = browser->rows = SLtt_Screen_Rows - 2; 198 browser->height = browser->rows = SLtt_Screen_Rows - 2;
199 browser->rows -= browser->extra_title_lines;
194 browser->y = 1; 200 browser->y = 1;
195 browser->x = 0; 201 browser->x = 0;
196} 202}
@@ -337,8 +343,8 @@ static int __ui_browser__refresh(struct ui_browser *browser)
337 else 343 else
338 width += 1; 344 width += 1;
339 345
340 SLsmg_fill_region(browser->y + row, browser->x, 346 SLsmg_fill_region(browser->y + row + browser->extra_title_lines, browser->x,
341 browser->height - row, width, ' '); 347 browser->rows - row, width, ' ');
342 348
343 return 0; 349 return 0;
344} 350}
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 {
17 u64 index, top_idx; 17 u64 index, top_idx;
18 void *top, *entries; 18 void *top, *entries;
19 u16 y, x, width, height, rows, columns, horiz_scroll; 19 u16 y, x, width, height, rows, columns, horiz_scroll;
20 u8 extra_title_lines;
20 int current_color; 21 int current_color;
21 void *priv; 22 void *priv;
22 const char *title; 23 const char *title;
@@ -38,6 +39,7 @@ bool ui_browser__is_current_entry(struct ui_browser *browser, unsigned row);
38void ui_browser__refresh_dimensions(struct ui_browser *browser); 39void ui_browser__refresh_dimensions(struct ui_browser *browser);
39void ui_browser__reset_index(struct ui_browser *browser); 40void ui_browser__reset_index(struct ui_browser *browser);
40 41
42void ui_browser__gotorc_title(struct ui_browser *browser, int y, int x);
41void ui_browser__gotorc(struct ui_browser *browser, int y, int x); 43void ui_browser__gotorc(struct ui_browser *browser, int y, int x);
42void ui_browser__write_nstring(struct ui_browser *browser, const char *msg, 44void ui_browser__write_nstring(struct ui_browser *browser, const char *msg,
43 unsigned int width); 45 unsigned int width);
diff --git a/tools/perf/ui/browsers/annotate.c b/tools/perf/ui/browsers/annotate.c
index c02fb437ac8e..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)
218 annotate_browser__draw_current_jump(browser); 218 annotate_browser__draw_current_jump(browser);
219 219
220 ui_browser__set_color(browser, HE_COLORSET_NORMAL); 220 ui_browser__set_color(browser, HE_COLORSET_NORMAL);
221 __ui_browser__vline(browser, pcnt_width, 0, browser->height - 1); 221 __ui_browser__vline(browser, pcnt_width, 0, browser->rows - 1);
222 return ret; 222 return ret;
223} 223}
224 224
@@ -592,21 +592,40 @@ bool annotate_browser__continue_search_reverse(struct annotate_browser *browser,
592 return __annotate_browser__search_reverse(browser); 592 return __annotate_browser__search_reverse(browser);
593} 593}
594 594
595static int annotate_browser__show(struct ui_browser *browser, char *title, const char *help)
596{
597 struct map_symbol *ms = browser->priv;
598 struct symbol *sym = ms->sym;
599 char symbol_dso[SYM_TITLE_MAX_SIZE];
600
601 if (ui_browser__show(browser, title, help) < 0)
602 return -1;
603
604 sym_title(sym, ms->map, symbol_dso, sizeof(symbol_dso));
605
606 ui_browser__gotorc_title(browser, 0, 0);
607 ui_browser__set_color(browser, HE_COLORSET_ROOT);
608 ui_browser__write_nstring(browser, symbol_dso, browser->width + 1);
609 return 0;
610}
611
595static int annotate_browser__run(struct annotate_browser *browser, 612static int annotate_browser__run(struct annotate_browser *browser,
596 struct perf_evsel *evsel, 613 struct perf_evsel *evsel,
597 struct hist_browser_timer *hbt) 614 struct hist_browser_timer *hbt)
598{ 615{
599 struct rb_node *nd = NULL; 616 struct rb_node *nd = NULL;
617 struct hists *hists = evsel__hists(evsel);
600 struct map_symbol *ms = browser->b.priv; 618 struct map_symbol *ms = browser->b.priv;
601 struct symbol *sym = ms->sym; 619 struct symbol *sym = ms->sym;
602 struct annotation *notes = symbol__annotation(ms->sym); 620 struct annotation *notes = symbol__annotation(ms->sym);
603 const char *help = "Press 'h' for help on key bindings"; 621 const char *help = "Press 'h' for help on key bindings";
604 int delay_secs = hbt ? hbt->refresh : 0; 622 int delay_secs = hbt ? hbt->refresh : 0;
623 char title[256];
605 int key; 624 int key;
606 char title[SYM_TITLE_MAX_SIZE];
607 625
608 sym_title(sym, ms->map, title, sizeof(title)); 626 annotation__scnprintf_samples_period(notes, title, sizeof(title), evsel);
609 if (ui_browser__show(&browser->b, title, help) < 0) 627
628 if (annotate_browser__show(&browser->b, title, help) < 0)
610 return -1; 629 return -1;
611 630
612 annotate_browser__calc_percent(browser, evsel); 631 annotate_browser__calc_percent(browser, evsel);
@@ -637,8 +656,11 @@ static int annotate_browser__run(struct annotate_browser *browser,
637 if (hbt) 656 if (hbt)
638 hbt->timer(hbt->arg); 657 hbt->timer(hbt->arg);
639 658
640 if (delay_secs != 0) 659 if (delay_secs != 0) {
641 symbol__annotate_decay_histogram(sym, evsel->idx); 660 symbol__annotate_decay_histogram(sym, evsel->idx);
661 hists__scnprintf_title(hists, title, sizeof(title));
662 annotate_browser__show(&browser->b, title, help);
663 }
642 continue; 664 continue;
643 case K_TAB: 665 case K_TAB:
644 if (nd != NULL) { 666 if (nd != NULL) {
@@ -812,6 +834,7 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map,
812 .seek = ui_browser__list_head_seek, 834 .seek = ui_browser__list_head_seek,
813 .write = annotate_browser__write, 835 .write = annotate_browser__write,
814 .filter = disasm_line__filter, 836 .filter = disasm_line__filter,
837 .extra_title_lines = 1, /* for hists__scnprintf_title() */
815 .priv = &ms, 838 .priv = &ms,
816 .use_navkeypressed = true, 839 .use_navkeypressed = true,
817 }, 840 },
diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c
index 8b4e82548f8e..0eec06c105c6 100644
--- a/tools/perf/ui/browsers/hists.c
+++ b/tools/perf/ui/browsers/hists.c
@@ -32,8 +32,7 @@
32 32
33extern void hist_browser__init_hpp(void); 33extern void hist_browser__init_hpp(void);
34 34
35static int perf_evsel_browser_title(struct hist_browser *browser, 35static int hists_browser__scnprintf_title(struct hist_browser *browser, char *bf, size_t size);
36 char *bf, size_t size);
37static void hist_browser__update_nr_entries(struct hist_browser *hb); 36static void hist_browser__update_nr_entries(struct hist_browser *hb);
38 37
39static struct rb_node *hists__filter_entries(struct rb_node *nd, 38static struct rb_node *hists__filter_entries(struct rb_node *nd,
@@ -62,6 +61,15 @@ static int hist_browser__get_folding(struct hist_browser *browser)
62 return unfolded_rows; 61 return unfolded_rows;
63} 62}
64 63
64static void hist_browser__set_title_space(struct hist_browser *hb)
65{
66 struct ui_browser *browser = &hb->b;
67 struct hists *hists = hb->hists;
68 struct perf_hpp_list *hpp_list = hists->hpp_list;
69
70 browser->extra_title_lines = hb->show_headers ? hpp_list->nr_header_lines : 0;
71}
72
65static u32 hist_browser__nr_entries(struct hist_browser *hb) 73static u32 hist_browser__nr_entries(struct hist_browser *hb)
66{ 74{
67 u32 nr_entries; 75 u32 nr_entries;
@@ -82,10 +90,16 @@ static void hist_browser__update_rows(struct hist_browser *hb)
82 struct ui_browser *browser = &hb->b; 90 struct ui_browser *browser = &hb->b;
83 struct hists *hists = hb->hists; 91 struct hists *hists = hb->hists;
84 struct perf_hpp_list *hpp_list = hists->hpp_list; 92 struct perf_hpp_list *hpp_list = hists->hpp_list;
85 u16 header_offset, index_row; 93 u16 index_row;
86 94
87 header_offset = hb->show_headers ? hpp_list->nr_header_lines : 0; 95 if (!hb->show_headers) {
88 browser->rows = browser->height - header_offset; 96 browser->rows += browser->extra_title_lines;
97 browser->extra_title_lines = 0;
98 return;
99 }
100
101 browser->extra_title_lines = hpp_list->nr_header_lines;
102 browser->rows -= browser->extra_title_lines;
89 /* 103 /*
90 * Verify if we were at the last line and that line isn't 104 * Verify if we were at the last line and that line isn't
91 * visibe because we now show the header line(s). 105 * visibe because we now show the header line(s).
@@ -108,17 +122,6 @@ static void hist_browser__refresh_dimensions(struct ui_browser *browser)
108 * changeset. 122 * changeset.
109 */ 123 */
110 ui_browser__refresh_dimensions(browser); 124 ui_browser__refresh_dimensions(browser);
111 hist_browser__update_rows(hb);
112}
113
114static void hist_browser__gotorc(struct hist_browser *browser, int row, int column)
115{
116 struct hists *hists = browser->hists;
117 struct perf_hpp_list *hpp_list = hists->hpp_list;
118 u16 header_offset;
119
120 header_offset = browser->show_headers ? hpp_list->nr_header_lines : 0;
121 ui_browser__gotorc(&browser->b, row + header_offset, column);
122} 125}
123 126
124static void hist_browser__reset(struct hist_browser *browser) 127static void hist_browser__reset(struct hist_browser *browser)
@@ -656,9 +659,10 @@ int hist_browser__run(struct hist_browser *browser, const char *help,
656 struct hist_entry *h = rb_entry(browser->b.top, 659 struct hist_entry *h = rb_entry(browser->b.top,
657 struct hist_entry, rb_node); 660 struct hist_entry, rb_node);
658 ui_helpline__pop(); 661 ui_helpline__pop();
659 ui_helpline__fpush("%d: nr_ent=(%d,%d), rows=%d, idx=%d, fve: idx=%d, row_off=%d, nrows=%d", 662 ui_helpline__fpush("%d: nr_ent=(%d,%d), etl: %d, rows=%d, idx=%d, fve: idx=%d, row_off=%d, nrows=%d",
660 seq++, browser->b.nr_entries, 663 seq++, browser->b.nr_entries,
661 browser->hists->nr_entries, 664 browser->hists->nr_entries,
665 browser->b.extra_title_lines,
662 browser->b.rows, 666 browser->b.rows,
663 browser->b.index, 667 browser->b.index,
664 browser->b.top_idx, 668 browser->b.top_idx,
@@ -733,7 +737,7 @@ static void hist_browser__show_callchain_entry(struct hist_browser *browser,
733 } 737 }
734 738
735 ui_browser__set_color(&browser->b, color); 739 ui_browser__set_color(&browser->b, color);
736 hist_browser__gotorc(browser, row, 0); 740 ui_browser__gotorc(&browser->b, row, 0);
737 ui_browser__write_nstring(&browser->b, " ", offset); 741 ui_browser__write_nstring(&browser->b, " ", offset);
738 ui_browser__printf(&browser->b, "%c", folded_sign); 742 ui_browser__printf(&browser->b, "%c", folded_sign);
739 ui_browser__write_graph(&browser->b, show_annotated ? SLSMG_RARROW_CHAR : ' '); 743 ui_browser__write_graph(&browser->b, show_annotated ? SLSMG_RARROW_CHAR : ' ');
@@ -1249,7 +1253,7 @@ static int hist_browser__show_entry(struct hist_browser *browser,
1249 }; 1253 };
1250 int column = 0; 1254 int column = 0;
1251 1255
1252 hist_browser__gotorc(browser, row, 0); 1256 ui_browser__gotorc(&browser->b, row, 0);
1253 1257
1254 hists__for_each_format(browser->hists, fmt) { 1258 hists__for_each_format(browser->hists, fmt) {
1255 char s[2048]; 1259 char s[2048];
@@ -1358,7 +1362,7 @@ static int hist_browser__show_hierarchy_entry(struct hist_browser *browser,
1358 goto show_callchain; 1362 goto show_callchain;
1359 } 1363 }
1360 1364
1361 hist_browser__gotorc(browser, row, 0); 1365 ui_browser__gotorc(&browser->b, row, 0);
1362 1366
1363 if (current_entry && browser->b.navkeypressed) 1367 if (current_entry && browser->b.navkeypressed)
1364 ui_browser__set_color(&browser->b, HE_COLORSET_SELECTED); 1368 ui_browser__set_color(&browser->b, HE_COLORSET_SELECTED);
@@ -1507,7 +1511,7 @@ static int hist_browser__show_no_entry(struct hist_browser *browser,
1507 browser->selection = NULL; 1511 browser->selection = NULL;
1508 } 1512 }
1509 1513
1510 hist_browser__gotorc(browser, row, 0); 1514 ui_browser__gotorc(&browser->b, row, 0);
1511 1515
1512 if (current_entry && browser->b.navkeypressed) 1516 if (current_entry && browser->b.navkeypressed)
1513 ui_browser__set_color(&browser->b, HE_COLORSET_SELECTED); 1517 ui_browser__set_color(&browser->b, HE_COLORSET_SELECTED);
@@ -1713,7 +1717,7 @@ static void hists_browser__headers(struct hist_browser *browser)
1713 hists_browser__scnprintf_headers(browser, headers, 1717 hists_browser__scnprintf_headers(browser, headers,
1714 sizeof(headers), line); 1718 sizeof(headers), line);
1715 1719
1716 ui_browser__gotorc(&browser->b, line, 0); 1720 ui_browser__gotorc_title(&browser->b, line, 0);
1717 ui_browser__set_color(&browser->b, HE_COLORSET_ROOT); 1721 ui_browser__set_color(&browser->b, HE_COLORSET_ROOT);
1718 ui_browser__write_nstring(&browser->b, headers, browser->b.width + 1); 1722 ui_browser__write_nstring(&browser->b, headers, browser->b.width + 1);
1719 } 1723 }
@@ -1740,17 +1744,11 @@ static void ui_browser__hists_init_top(struct ui_browser *browser)
1740static unsigned int hist_browser__refresh(struct ui_browser *browser) 1744static unsigned int hist_browser__refresh(struct ui_browser *browser)
1741{ 1745{
1742 unsigned row = 0; 1746 unsigned row = 0;
1743 u16 header_offset = 0;
1744 struct rb_node *nd; 1747 struct rb_node *nd;
1745 struct hist_browser *hb = container_of(browser, struct hist_browser, b); 1748 struct hist_browser *hb = container_of(browser, struct hist_browser, b);
1746 struct hists *hists = hb->hists;
1747
1748 if (hb->show_headers) {
1749 struct perf_hpp_list *hpp_list = hists->hpp_list;
1750 1749
1750 if (hb->show_headers)
1751 hist_browser__show_headers(hb); 1751 hist_browser__show_headers(hb);
1752 header_offset = hpp_list->nr_header_lines;
1753 }
1754 1752
1755 ui_browser__hists_init_top(browser); 1753 ui_browser__hists_init_top(browser);
1756 hb->he_selection = NULL; 1754 hb->he_selection = NULL;
@@ -1788,7 +1786,7 @@ static unsigned int hist_browser__refresh(struct ui_browser *browser)
1788 break; 1786 break;
1789 } 1787 }
1790 1788
1791 return row + header_offset; 1789 return row;
1792} 1790}
1793 1791
1794static struct rb_node *hists__filter_entries(struct rb_node *nd, 1792static struct rb_node *hists__filter_entries(struct rb_node *nd,
@@ -2143,6 +2141,7 @@ void hist_browser__init(struct hist_browser *browser,
2143 browser->b.seek = ui_browser__hists_seek; 2141 browser->b.seek = ui_browser__hists_seek;
2144 browser->b.use_navkeypressed = true; 2142 browser->b.use_navkeypressed = true;
2145 browser->show_headers = symbol_conf.show_hist_headers; 2143 browser->show_headers = symbol_conf.show_hist_headers;
2144 hist_browser__set_title_space(browser);
2146 2145
2147 if (symbol_conf.report_hierarchy) { 2146 if (symbol_conf.report_hierarchy) {
2148 struct perf_hpp_list_node *fmt_node; 2147 struct perf_hpp_list_node *fmt_node;
@@ -2183,7 +2182,7 @@ perf_evsel_browser__new(struct perf_evsel *evsel,
2183 if (browser) { 2182 if (browser) {
2184 browser->hbt = hbt; 2183 browser->hbt = hbt;
2185 browser->env = env; 2184 browser->env = env;
2186 browser->title = perf_evsel_browser_title; 2185 browser->title = hists_browser__scnprintf_title;
2187 } 2186 }
2188 return browser; 2187 return browser;
2189} 2188}
@@ -2209,84 +2208,11 @@ static inline bool is_report_browser(void *timer)
2209 return timer == NULL; 2208 return timer == NULL;
2210} 2209}
2211 2210
2212static int perf_evsel_browser_title(struct hist_browser *browser, 2211static int hists_browser__scnprintf_title(struct hist_browser *browser, char *bf, size_t size)
2213 char *bf, size_t size)
2214{ 2212{
2215 struct hist_browser_timer *hbt = browser->hbt; 2213 struct hist_browser_timer *hbt = browser->hbt;
2216 struct hists *hists = browser->hists; 2214 int printed = __hists__scnprintf_title(browser->hists, bf, size, !is_report_browser(hbt));
2217 char unit;
2218 int printed;
2219 const struct dso *dso = hists->dso_filter;
2220 const struct thread *thread = hists->thread_filter;
2221 int socket_id = hists->socket_filter;
2222 unsigned long nr_samples = hists->stats.nr_events[PERF_RECORD_SAMPLE];
2223 u64 nr_events = hists->stats.total_period;
2224 struct perf_evsel *evsel = hists_to_evsel(hists);
2225 const char *ev_name = perf_evsel__name(evsel);
2226 char buf[512], sample_freq_str[64] = "";
2227 size_t buflen = sizeof(buf);
2228 char ref[30] = " show reference callgraph, ";
2229 bool enable_ref = false;
2230 2215
2231 if (symbol_conf.filter_relative) {
2232 nr_samples = hists->stats.nr_non_filtered_samples;
2233 nr_events = hists->stats.total_non_filtered_period;
2234 }
2235
2236 if (perf_evsel__is_group_event(evsel)) {
2237 struct perf_evsel *pos;
2238
2239 perf_evsel__group_desc(evsel, buf, buflen);
2240 ev_name = buf;
2241
2242 for_each_group_member(pos, evsel) {
2243 struct hists *pos_hists = evsel__hists(pos);
2244
2245 if (symbol_conf.filter_relative) {
2246 nr_samples += pos_hists->stats.nr_non_filtered_samples;
2247 nr_events += pos_hists->stats.total_non_filtered_period;
2248 } else {
2249 nr_samples += pos_hists->stats.nr_events[PERF_RECORD_SAMPLE];
2250 nr_events += pos_hists->stats.total_period;
2251 }
2252 }
2253 }
2254
2255 if (symbol_conf.show_ref_callgraph &&
2256 strstr(ev_name, "call-graph=no"))
2257 enable_ref = true;
2258
2259 if (!is_report_browser(hbt))
2260 scnprintf(sample_freq_str, sizeof(sample_freq_str), " %d Hz,", evsel->attr.sample_freq);
2261
2262 nr_samples = convert_unit(nr_samples, &unit);
2263 printed = scnprintf(bf, size,
2264 "Samples: %lu%c of event%s '%s',%s%sEvent count (approx.): %" PRIu64,
2265 nr_samples, unit, evsel->nr_members > 1 ? "s" : "",
2266 ev_name, sample_freq_str, enable_ref ? ref : " ", nr_events);
2267
2268
2269 if (hists->uid_filter_str)
2270 printed += snprintf(bf + printed, size - printed,
2271 ", UID: %s", hists->uid_filter_str);
2272 if (thread) {
2273 if (hists__has(hists, thread)) {
2274 printed += scnprintf(bf + printed, size - printed,
2275 ", Thread: %s(%d)",
2276 (thread->comm_set ? thread__comm_str(thread) : ""),
2277 thread->tid);
2278 } else {
2279 printed += scnprintf(bf + printed, size - printed,
2280 ", Thread: %s",
2281 (thread->comm_set ? thread__comm_str(thread) : ""));
2282 }
2283 }
2284 if (dso)
2285 printed += scnprintf(bf + printed, size - printed,
2286 ", DSO: %s", dso->short_name);
2287 if (socket_id > -1)
2288 printed += scnprintf(bf + printed, size - printed,
2289 ", Processor Socket: %d", socket_id);
2290 if (!is_report_browser(hbt)) { 2216 if (!is_report_browser(hbt)) {
2291 struct perf_top *top = hbt->arg; 2217 struct perf_top *top = hbt->arg;
2292 2218
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index 3a428d7c59b9..fbad8dfbb186 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -17,6 +17,7 @@
17#include "config.h" 17#include "config.h"
18#include "cache.h" 18#include "cache.h"
19#include "symbol.h" 19#include "symbol.h"
20#include "units.h"
20#include "debug.h" 21#include "debug.h"
21#include "annotate.h" 22#include "annotate.h"
22#include "evsel.h" 23#include "evsel.h"
@@ -2324,7 +2325,7 @@ int symbol__tty_annotate2(struct symbol *sym, struct map *map,
2324 struct dso *dso = map->dso; 2325 struct dso *dso = map->dso;
2325 struct rb_root source_line = RB_ROOT; 2326 struct rb_root source_line = RB_ROOT;
2326 struct annotation_options opts = annotation__default_options; 2327 struct annotation_options opts = annotation__default_options;
2327 const char *ev_name = perf_evsel__name(evsel); 2328 struct annotation *notes = symbol__annotation(sym);
2328 char buf[1024]; 2329 char buf[1024];
2329 2330
2330 if (symbol__annotate2(sym, map, evsel, &opts, NULL) < 0) 2331 if (symbol__annotate2(sym, map, evsel, &opts, NULL) < 0)
@@ -2336,12 +2337,8 @@ int symbol__tty_annotate2(struct symbol *sym, struct map *map,
2336 print_summary(&source_line, dso->long_name); 2337 print_summary(&source_line, dso->long_name);
2337 } 2338 }
2338 2339
2339 if (perf_evsel__is_group_event(evsel)) { 2340 annotation__scnprintf_samples_period(notes, buf, sizeof(buf), evsel);
2340 perf_evsel__group_desc(evsel, buf, sizeof(buf)); 2341 fprintf(stdout, "%s\n%s() %s\n", buf, sym->name, dso->long_name);
2341 ev_name = buf;
2342 }
2343
2344 fprintf(stdout, "%s() %s\nEvent: %s\n\n", sym->name, dso->long_name, ev_name);
2345 symbol__annotate_fprintf2(sym, stdout); 2342 symbol__annotate_fprintf2(sym, stdout);
2346 2343
2347 annotated_source__purge(symbol__annotation(sym)->src); 2344 annotated_source__purge(symbol__annotation(sym)->src);
@@ -2597,6 +2594,46 @@ out_free_offsets:
2597 return -1; 2594 return -1;
2598} 2595}
2599 2596
2597int __annotation__scnprintf_samples_period(struct annotation *notes,
2598 char *bf, size_t size,
2599 struct perf_evsel *evsel,
2600 bool show_freq)
2601{
2602 const char *ev_name = perf_evsel__name(evsel);
2603 char buf[1024], ref[30] = " show reference callgraph, ";
2604 char sample_freq_str[64] = "";
2605 unsigned long nr_samples = 0;
2606 int nr_members = 1;
2607 bool enable_ref = false;
2608 u64 nr_events = 0;
2609 char unit;
2610 int i;
2611
2612 if (perf_evsel__is_group_event(evsel)) {
2613 perf_evsel__group_desc(evsel, buf, sizeof(buf));
2614 ev_name = buf;
2615 nr_members = evsel->nr_members;
2616 }
2617
2618 for (i = 0; i < nr_members; i++) {
2619 struct sym_hist *ah = annotation__histogram(notes, evsel->idx + i);
2620
2621 nr_samples += ah->nr_samples;
2622 nr_events += ah->period;
2623 }
2624
2625 if (symbol_conf.show_ref_callgraph && strstr(ev_name, "call-graph=no"))
2626 enable_ref = true;
2627
2628 if (show_freq)
2629 scnprintf(sample_freq_str, sizeof(sample_freq_str), " %d Hz,", evsel->attr.sample_freq);
2630
2631 nr_samples = convert_unit(nr_samples, &unit);
2632 return scnprintf(bf, size, "Samples: %lu%c of event%s '%s',%s%sEvent count (approx.): %" PRIu64,
2633 nr_samples, unit, evsel->nr_members > 1 ? "s" : "",
2634 ev_name, sample_freq_str, enable_ref ? ref : " ", nr_events);
2635}
2636
2600#define ANNOTATION__CFG(n) \ 2637#define ANNOTATION__CFG(n) \
2601 { .name = #n, .value = &annotation__default_options.n, } 2638 { .name = #n, .value = &annotation__default_options.n, }
2602 2639
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
151void annotation_line__write(struct annotation_line *al, struct annotation *notes, 151void annotation_line__write(struct annotation_line *al, struct annotation *notes,
152 struct annotation_write_ops *ops); 152 struct annotation_write_ops *ops);
153 153
154int __annotation__scnprintf_samples_period(struct annotation *notes,
155 char *bf, size_t size,
156 struct perf_evsel *evsel,
157 bool show_freq);
158
159static inline int annotation__scnprintf_samples_period(struct annotation *notes,
160 char *bf, size_t size,
161 struct perf_evsel *evsel)
162{
163 return __annotation__scnprintf_samples_period(notes, bf, size, evsel, true);
164}
165
154int disasm_line__scnprintf(struct disasm_line *dl, char *bf, size_t size, bool raw); 166int disasm_line__scnprintf(struct disasm_line *dl, char *bf, size_t size, bool raw);
155size_t disasm__fprintf(struct list_head *head, FILE *fp); 167size_t disasm__fprintf(struct list_head *head, FILE *fp);
156void symbol__calc_percent(struct symbol *sym, struct perf_evsel *evsel); 168void symbol__calc_percent(struct symbol *sym, struct perf_evsel *evsel);
diff --git a/tools/perf/util/auxtrace.c b/tools/perf/util/auxtrace.c
index fb357a00dd86..857de69a5361 100644
--- a/tools/perf/util/auxtrace.c
+++ b/tools/perf/util/auxtrace.c
@@ -302,13 +302,27 @@ static int auxtrace_queues__split_buffer(struct auxtrace_queues *queues,
302 return 0; 302 return 0;
303} 303}
304 304
305static bool filter_cpu(struct perf_session *session, int cpu)
306{
307 unsigned long *cpu_bitmap = session->itrace_synth_opts->cpu_bitmap;
308
309 return cpu_bitmap && cpu != -1 && !test_bit(cpu, cpu_bitmap);
310}
311
305static int auxtrace_queues__add_buffer(struct auxtrace_queues *queues, 312static int auxtrace_queues__add_buffer(struct auxtrace_queues *queues,
306 struct perf_session *session, 313 struct perf_session *session,
307 unsigned int idx, 314 unsigned int idx,
308 struct auxtrace_buffer *buffer, 315 struct auxtrace_buffer *buffer,
309 struct auxtrace_buffer **buffer_ptr) 316 struct auxtrace_buffer **buffer_ptr)
310{ 317{
311 int err; 318 int err = -ENOMEM;
319
320 if (filter_cpu(session, buffer->cpu))
321 return 0;
322
323 buffer = memdup(buffer, sizeof(*buffer));
324 if (!buffer)
325 return -ENOMEM;
312 326
313 if (session->one_mmap) { 327 if (session->one_mmap) {
314 buffer->data = buffer->data_offset - session->one_mmap_offset + 328 buffer->data = buffer->data_offset - session->one_mmap_offset +
@@ -316,31 +330,28 @@ static int auxtrace_queues__add_buffer(struct auxtrace_queues *queues,
316 } else if (perf_data__is_pipe(session->data)) { 330 } else if (perf_data__is_pipe(session->data)) {
317 buffer->data = auxtrace_copy_data(buffer->size, session); 331 buffer->data = auxtrace_copy_data(buffer->size, session);
318 if (!buffer->data) 332 if (!buffer->data)
319 return -ENOMEM; 333 goto out_free;
320 buffer->data_needs_freeing = true; 334 buffer->data_needs_freeing = true;
321 } else if (BITS_PER_LONG == 32 && 335 } else if (BITS_PER_LONG == 32 &&
322 buffer->size > BUFFER_LIMIT_FOR_32_BIT) { 336 buffer->size > BUFFER_LIMIT_FOR_32_BIT) {
323 err = auxtrace_queues__split_buffer(queues, idx, buffer); 337 err = auxtrace_queues__split_buffer(queues, idx, buffer);
324 if (err) 338 if (err)
325 return err; 339 goto out_free;
326 } 340 }
327 341
328 err = auxtrace_queues__queue_buffer(queues, idx, buffer); 342 err = auxtrace_queues__queue_buffer(queues, idx, buffer);
329 if (err) 343 if (err)
330 return err; 344 goto out_free;
331 345
332 /* FIXME: Doesn't work for split buffer */ 346 /* FIXME: Doesn't work for split buffer */
333 if (buffer_ptr) 347 if (buffer_ptr)
334 *buffer_ptr = buffer; 348 *buffer_ptr = buffer;
335 349
336 return 0; 350 return 0;
337}
338 351
339static bool filter_cpu(struct perf_session *session, int cpu) 352out_free:
340{ 353 auxtrace_buffer__free(buffer);
341 unsigned long *cpu_bitmap = session->itrace_synth_opts->cpu_bitmap; 354 return err;
342
343 return cpu_bitmap && cpu != -1 && !test_bit(cpu, cpu_bitmap);
344} 355}
345 356
346int auxtrace_queues__add_event(struct auxtrace_queues *queues, 357int auxtrace_queues__add_event(struct auxtrace_queues *queues,
@@ -348,36 +359,19 @@ int auxtrace_queues__add_event(struct auxtrace_queues *queues,
348 union perf_event *event, off_t data_offset, 359 union perf_event *event, off_t data_offset,
349 struct auxtrace_buffer **buffer_ptr) 360 struct auxtrace_buffer **buffer_ptr)
350{ 361{
351 struct auxtrace_buffer *buffer; 362 struct auxtrace_buffer buffer = {
352 unsigned int idx; 363 .pid = -1,
353 int err; 364 .tid = event->auxtrace.tid,
354 365 .cpu = event->auxtrace.cpu,
355 if (filter_cpu(session, event->auxtrace.cpu)) 366 .data_offset = data_offset,
356 return 0; 367 .offset = event->auxtrace.offset,
357 368 .reference = event->auxtrace.reference,
358 buffer = zalloc(sizeof(struct auxtrace_buffer)); 369 .size = event->auxtrace.size,
359 if (!buffer) 370 };
360 return -ENOMEM; 371 unsigned int idx = event->auxtrace.idx;
361
362 buffer->pid = -1;
363 buffer->tid = event->auxtrace.tid;
364 buffer->cpu = event->auxtrace.cpu;
365 buffer->data_offset = data_offset;
366 buffer->offset = event->auxtrace.offset;
367 buffer->reference = event->auxtrace.reference;
368 buffer->size = event->auxtrace.size;
369 idx = event->auxtrace.idx;
370
371 err = auxtrace_queues__add_buffer(queues, session, idx, buffer,
372 buffer_ptr);
373 if (err)
374 goto out_err;
375
376 return 0;
377 372
378out_err: 373 return auxtrace_queues__add_buffer(queues, session, idx, &buffer,
379 auxtrace_buffer__free(buffer); 374 buffer_ptr);
380 return err;
381} 375}
382 376
383static int auxtrace_queues__add_indexed_event(struct auxtrace_queues *queues, 377static int auxtrace_queues__add_indexed_event(struct auxtrace_queues *queues,
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)
41 if (!M) 41 if (!M)
42 return -1; 42 return -1;
43 for (llvm::Function& F : *M) 43 for (llvm::Function& F : *M)
44 if (F.getName() == "bpf_func__SyS_epoll_wait") 44 if (F.getName() == "bpf_func__SyS_epoll_pwait")
45 return 0; 45 return 0;
46 return -1; 46 return -1;
47} 47}
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 @@
9 * Copyright (C) 2016 Huawei Inc. 9 * Copyright (C) 2016 Huawei Inc.
10 */ 10 */
11 11
12#include "clang/Basic/Version.h"
12#include "clang/CodeGen/CodeGenAction.h" 13#include "clang/CodeGen/CodeGenAction.h"
13#include "clang/Frontend/CompilerInvocation.h" 14#include "clang/Frontend/CompilerInvocation.h"
14#include "clang/Frontend/CompilerInstance.h" 15#include "clang/Frontend/CompilerInstance.h"
@@ -58,7 +59,8 @@ createCompilerInvocation(llvm::opt::ArgStringList CFlags, StringRef& Path,
58 59
59 FrontendOptions& Opts = CI->getFrontendOpts(); 60 FrontendOptions& Opts = CI->getFrontendOpts();
60 Opts.Inputs.clear(); 61 Opts.Inputs.clear();
61 Opts.Inputs.emplace_back(Path, IK_C); 62 Opts.Inputs.emplace_back(Path,
63 FrontendOptions::getInputKindForExtension("c"));
62 return CI; 64 return CI;
63} 65}
64 66
@@ -71,10 +73,17 @@ getModuleFromSource(llvm::opt::ArgStringList CFlags,
71 73
72 Clang.setVirtualFileSystem(&*VFS); 74 Clang.setVirtualFileSystem(&*VFS);
73 75
76#if CLANG_VERSION_MAJOR < 4
74 IntrusiveRefCntPtr<CompilerInvocation> CI = 77 IntrusiveRefCntPtr<CompilerInvocation> CI =
75 createCompilerInvocation(std::move(CFlags), Path, 78 createCompilerInvocation(std::move(CFlags), Path,
76 Clang.getDiagnostics()); 79 Clang.getDiagnostics());
77 Clang.setInvocation(&*CI); 80 Clang.setInvocation(&*CI);
81#else
82 std::shared_ptr<CompilerInvocation> CI(
83 createCompilerInvocation(std::move(CFlags), Path,
84 Clang.getDiagnostics()));
85 Clang.setInvocation(CI);
86#endif
78 87
79 std::unique_ptr<CodeGenAction> Act(new EmitLLVMOnlyAction(&*LLVMCtx)); 88 std::unique_ptr<CodeGenAction> Act(new EmitLLVMOnlyAction(&*LLVMCtx));
80 if (!Clang.ExecuteAction(*Act)) 89 if (!Clang.ExecuteAction(*Act))
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)
979 return ret < 0 ? ret : strbuf_addf(buf, "\t%s", dwarf_diename(vr_die)); 979 return ret < 0 ? ret : strbuf_addf(buf, "\t%s", dwarf_diename(vr_die));
980} 980}
981 981
982#ifdef HAVE_DWARF_GETLOCATIONS 982#ifdef HAVE_DWARF_GETLOCATIONS_SUPPORT
983/** 983/**
984 * die_get_var_innermost_scope - Get innermost scope range of given variable DIE 984 * die_get_var_innermost_scope - Get innermost scope range of given variable DIE
985 * @sp_die: a subprogram DIE 985 * @sp_die: a subprogram DIE
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 @@
6#include "session.h" 6#include "session.h"
7#include "namespaces.h" 7#include "namespaces.h"
8#include "sort.h" 8#include "sort.h"
9#include "units.h"
9#include "evlist.h" 10#include "evlist.h"
10#include "evsel.h" 11#include "evsel.h"
11#include "annotate.h" 12#include "annotate.h"
@@ -14,6 +15,7 @@
14#include "ui/progress.h" 15#include "ui/progress.h"
15#include <errno.h> 16#include <errno.h>
16#include <math.h> 17#include <math.h>
18#include <inttypes.h>
17#include <sys/param.h> 19#include <sys/param.h>
18 20
19static bool hists__filter_entry_by_dso(struct hists *hists, 21static bool hists__filter_entry_by_dso(struct hists *hists,
@@ -2454,6 +2456,85 @@ u64 hists__total_period(struct hists *hists)
2454 hists->stats.total_period; 2456 hists->stats.total_period;
2455} 2457}
2456 2458
2459int __hists__scnprintf_title(struct hists *hists, char *bf, size_t size, bool show_freq)
2460{
2461 char unit;
2462 int printed;
2463 const struct dso *dso = hists->dso_filter;
2464 const struct thread *thread = hists->thread_filter;
2465 int socket_id = hists->socket_filter;
2466 unsigned long nr_samples = hists->stats.nr_events[PERF_RECORD_SAMPLE];
2467 u64 nr_events = hists->stats.total_period;
2468 struct perf_evsel *evsel = hists_to_evsel(hists);
2469 const char *ev_name = perf_evsel__name(evsel);
2470 char buf[512], sample_freq_str[64] = "";
2471 size_t buflen = sizeof(buf);
2472 char ref[30] = " show reference callgraph, ";
2473 bool enable_ref = false;
2474
2475 if (symbol_conf.filter_relative) {
2476 nr_samples = hists->stats.nr_non_filtered_samples;
2477 nr_events = hists->stats.total_non_filtered_period;
2478 }
2479
2480 if (perf_evsel__is_group_event(evsel)) {
2481 struct perf_evsel *pos;
2482
2483 perf_evsel__group_desc(evsel, buf, buflen);
2484 ev_name = buf;
2485
2486 for_each_group_member(pos, evsel) {
2487 struct hists *pos_hists = evsel__hists(pos);
2488
2489 if (symbol_conf.filter_relative) {
2490 nr_samples += pos_hists->stats.nr_non_filtered_samples;
2491 nr_events += pos_hists->stats.total_non_filtered_period;
2492 } else {
2493 nr_samples += pos_hists->stats.nr_events[PERF_RECORD_SAMPLE];
2494 nr_events += pos_hists->stats.total_period;
2495 }
2496 }
2497 }
2498
2499 if (symbol_conf.show_ref_callgraph &&
2500 strstr(ev_name, "call-graph=no"))
2501 enable_ref = true;
2502
2503 if (show_freq)
2504 scnprintf(sample_freq_str, sizeof(sample_freq_str), " %d Hz,", evsel->attr.sample_freq);
2505
2506 nr_samples = convert_unit(nr_samples, &unit);
2507 printed = scnprintf(bf, size,
2508 "Samples: %lu%c of event%s '%s',%s%sEvent count (approx.): %" PRIu64,
2509 nr_samples, unit, evsel->nr_members > 1 ? "s" : "",
2510 ev_name, sample_freq_str, enable_ref ? ref : " ", nr_events);
2511
2512
2513 if (hists->uid_filter_str)
2514 printed += snprintf(bf + printed, size - printed,
2515 ", UID: %s", hists->uid_filter_str);
2516 if (thread) {
2517 if (hists__has(hists, thread)) {
2518 printed += scnprintf(bf + printed, size - printed,
2519 ", Thread: %s(%d)",
2520 (thread->comm_set ? thread__comm_str(thread) : ""),
2521 thread->tid);
2522 } else {
2523 printed += scnprintf(bf + printed, size - printed,
2524 ", Thread: %s",
2525 (thread->comm_set ? thread__comm_str(thread) : ""));
2526 }
2527 }
2528 if (dso)
2529 printed += scnprintf(bf + printed, size - printed,
2530 ", DSO: %s", dso->short_name);
2531 if (socket_id > -1)
2532 printed += scnprintf(bf + printed, size - printed,
2533 ", Processor Socket: %d", socket_id);
2534
2535 return printed;
2536}
2537
2457int parse_filter_percentage(const struct option *opt __maybe_unused, 2538int parse_filter_percentage(const struct option *opt __maybe_unused,
2458 const char *arg, int unset __maybe_unused) 2539 const char *arg, int unset __maybe_unused)
2459{ 2540{
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index e869cad4d89f..fbabfd8a215d 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -61,6 +61,7 @@ enum hist_column {
61 HISTC_SRCLINE_TO, 61 HISTC_SRCLINE_TO,
62 HISTC_TRACE, 62 HISTC_TRACE,
63 HISTC_SYM_SIZE, 63 HISTC_SYM_SIZE,
64 HISTC_DSO_SIZE,
64 HISTC_NR_COLS, /* Last entry */ 65 HISTC_NR_COLS, /* Last entry */
65}; 66};
66 67
@@ -503,5 +504,11 @@ int __hpp__slsmg_color_printf(struct perf_hpp *hpp, const char *fmt, ...);
503int __hist_entry__snprintf(struct hist_entry *he, struct perf_hpp *hpp, 504int __hist_entry__snprintf(struct hist_entry *he, struct perf_hpp *hpp,
504 struct perf_hpp_list *hpp_list); 505 struct perf_hpp_list *hpp_list);
505int hists__fprintf_headers(struct hists *hists, FILE *fp); 506int hists__fprintf_headers(struct hists *hists, FILE *fp);
507int __hists__scnprintf_title(struct hists *hists, char *bf, size_t size, bool show_freq);
508
509static inline int hists__scnprintf_title(struct hists *hists, char *bf, size_t size)
510{
511 return __hists__scnprintf_title(hists, bf, size, true);
512}
506 513
507#endif /* __PERF_HIST_H */ 514#endif /* __PERF_HIST_H */
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)
103 return ip; 103 return ip;
104} 104}
105 105
106static inline size_t map__size(const struct map *map)
107{
108 return map->end - map->start;
109}
106 110
107/* rip/ip <-> addr suitable for passing to `objdump --start-address=` */ 111/* rip/ip <-> addr suitable for passing to `objdump --start-address=` */
108u64 map__rip_2objdump(struct map *map, u64 rip); 112u64 map__rip_2objdump(struct map *map, u64 rip);
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)
1591 drop_rate = (double)stats->total_lost_samples / 1591 drop_rate = (double)stats->total_lost_samples /
1592 (double) (stats->nr_events[PERF_RECORD_SAMPLE] + stats->total_lost_samples); 1592 (double) (stats->nr_events[PERF_RECORD_SAMPLE] + stats->total_lost_samples);
1593 if (drop_rate > 0.05) { 1593 if (drop_rate > 0.05) {
1594 ui__warning("Processed %" PRIu64 " samples and lost %3.2f%% samples!\n\n", 1594 ui__warning("Processed %" PRIu64 " samples and lost %3.2f%%!\n\n",
1595 stats->nr_events[PERF_RECORD_SAMPLE] + stats->total_lost_samples, 1595 stats->nr_events[PERF_RECORD_SAMPLE] + stats->total_lost_samples,
1596 drop_rate * 100.0); 1596 drop_rate * 100.0);
1597 } 1597 }
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 = {
1545 .se_width_idx = HISTC_SYM_SIZE, 1545 .se_width_idx = HISTC_SYM_SIZE,
1546}; 1546};
1547 1547
1548/* --sort dso_size */
1549
1550static int64_t _sort__dso_size_cmp(struct map *map_l, struct map *map_r)
1551{
1552 int64_t size_l = map_l != NULL ? map__size(map_l) : 0;
1553 int64_t size_r = map_r != NULL ? map__size(map_r) : 0;
1554
1555 return size_l < size_r ? -1 :
1556 size_l == size_r ? 0 : 1;
1557}
1558
1559static int64_t
1560sort__dso_size_cmp(struct hist_entry *left, struct hist_entry *right)
1561{
1562 return _sort__dso_size_cmp(right->ms.map, left->ms.map);
1563}
1564
1565static int _hist_entry__dso_size_snprintf(struct map *map, char *bf,
1566 size_t bf_size, unsigned int width)
1567{
1568 if (map && map->dso)
1569 return repsep_snprintf(bf, bf_size, "%*d", width,
1570 map__size(map));
1571
1572 return repsep_snprintf(bf, bf_size, "%*s", width, "unknown");
1573}
1574
1575static int hist_entry__dso_size_snprintf(struct hist_entry *he, char *bf,
1576 size_t size, unsigned int width)
1577{
1578 return _hist_entry__dso_size_snprintf(he->ms.map, bf, size, width);
1579}
1580
1581struct sort_entry sort_dso_size = {
1582 .se_header = "DSO size",
1583 .se_cmp = sort__dso_size_cmp,
1584 .se_snprintf = hist_entry__dso_size_snprintf,
1585 .se_width_idx = HISTC_DSO_SIZE,
1586};
1587
1548 1588
1549struct sort_dimension { 1589struct sort_dimension {
1550 const char *name; 1590 const char *name;
@@ -1569,6 +1609,7 @@ static struct sort_dimension common_sort_dimensions[] = {
1569 DIM(SORT_TRANSACTION, "transaction", sort_transaction), 1609 DIM(SORT_TRANSACTION, "transaction", sort_transaction),
1570 DIM(SORT_TRACE, "trace", sort_trace), 1610 DIM(SORT_TRACE, "trace", sort_trace),
1571 DIM(SORT_SYM_SIZE, "symbol_size", sort_sym_size), 1611 DIM(SORT_SYM_SIZE, "symbol_size", sort_sym_size),
1612 DIM(SORT_DSO_SIZE, "dso_size", sort_dso_size),
1572 DIM(SORT_CGROUP_ID, "cgroup_id", sort_cgroup_id), 1613 DIM(SORT_CGROUP_ID, "cgroup_id", sort_cgroup_id),
1573}; 1614};
1574 1615
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 {
220 SORT_TRANSACTION, 220 SORT_TRANSACTION,
221 SORT_TRACE, 221 SORT_TRACE,
222 SORT_SYM_SIZE, 222 SORT_SYM_SIZE,
223 SORT_DSO_SIZE,
223 SORT_CGROUP_ID, 224 SORT_CGROUP_ID,
224 225
225 /* branch stack specific sort keys */ 226 /* branch stack specific sort keys */
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 @@
11#include <stdlib.h> 11#include <stdlib.h>
12#include <stdarg.h> 12#include <stdarg.h>
13#include <linux/compiler.h> 13#include <linux/compiler.h>
14#include <linux/types.h> 14#include <sys/types.h>
15#include "namespaces.h"
16 15
17/* General helper functions */ 16/* General helper functions */
18void usage(const char *err) __noreturn; 17void usage(const char *err) __noreturn;
@@ -26,6 +25,7 @@ static inline void *zalloc(size_t size)
26#define zfree(ptr) ({ free(*ptr); *ptr = NULL; }) 25#define zfree(ptr) ({ free(*ptr); *ptr = NULL; })
27 26
28struct dirent; 27struct dirent;
28struct nsinfo;
29struct strlist; 29struct strlist;
30 30
31int mkdir_p(char *path, mode_t mode); 31int mkdir_p(char *path, mode_t mode);