diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2018-04-15 15:36:31 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2018-04-15 15:36:31 -0400 |
commit | 174e719439b8224d7cedfbdd9529de396cac01ff (patch) | |
tree | a1729ca869e7dedaa47199d0818b2297521076a5 | |
parent | 19ca90de49c3269874722148edf07083182e23ec (diff) | |
parent | 32e6e967fb36bf77ed99221ae3ce1909f045d8f9 (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 ')'
...
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) |
1364 | struct drm_intel_sprite_colorkey { | 1368 | struct 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 | ||
1620 | struct 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 | |||
1645 | struct 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 | */ | ||
1686 | struct 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 @@ | |||
1 | perf-version(1) | ||
2 | =============== | ||
3 | |||
4 | NAME | ||
5 | ---- | ||
6 | perf-version - display the version of perf binary | ||
7 | |||
8 | SYNOPSIS | ||
9 | -------- | ||
10 | 'perf version' [--build-options] | ||
11 | |||
12 | DESCRIPTION | ||
13 | ----------- | ||
14 | With no options given, the 'perf version' prints the perf version | ||
15 | on the standard output. | ||
16 | |||
17 | If the option '--build-options' is given, then the status of | ||
18 | compiled-in libraries are printed on the standard output. | ||
19 | |||
20 | OPTIONS | ||
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 |
353 | endif # NO_LIBELF | 353 | endif # NO_LIBELF |
354 | 354 | ||
355 | ifeq ($(feature-glibc), 1) | ||
356 | CFLAGS += -DHAVE_GLIBC_SUPPORT | ||
357 | endif | ||
358 | |||
355 | ifdef NO_DWARF | 359 | ifdef NO_DWARF |
356 | NO_LIBDW_DWARF_UNWIND := 1 | 360 | NO_LIBDW_DWARF_UNWIND := 1 |
357 | endif | 361 | endif |
@@ -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 |
640 | endif | 645 | endif |
@@ -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 | ||
365 | ifeq ($(USE_CLANG), 1) | 365 | ifeq ($(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 |
369 | endif | 370 | endif |
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 | ||
7 | int cmd_version(int argc __maybe_unused, const char **argv __maybe_unused) | 11 | int version_verbose; |
12 | |||
13 | struct version { | ||
14 | bool build_options; | ||
15 | }; | ||
16 | |||
17 | static struct version version; | ||
18 | |||
19 | static struct option version_options[] = { | ||
20 | OPT_BOOLEAN(0, "build-options", &version.build_options, | ||
21 | "display the build options"), | ||
22 | }; | ||
23 | |||
24 | static const char * const version_usage[] = { | ||
25 | "perf version [<options>]", | ||
26 | NULL | ||
27 | }; | ||
28 | |||
29 | static 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 | |||
41 | static 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) \ | ||
50 | do { \ | ||
51 | if (IS_BUILTIN(__d)) \ | ||
52 | status_print(#__m, #__d, "on"); \ | ||
53 | else \ | ||
54 | status_print(#__m, #__d, "OFF"); \ | ||
55 | } while (0) | ||
56 | |||
57 | static 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 | |||
80 | int 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 { | |||
84 | struct option; | 84 | struct option; |
85 | extern const char * const *record_usage; | 85 | extern const char * const *record_usage; |
86 | extern struct option *record_options; | 86 | extern struct option *record_options; |
87 | extern int version_verbose; | ||
87 | 88 | ||
88 | int record__parse_freq(const struct option *opt, const char *str, int unset); | 89 | int 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 | ||
48 | void ui_browser__gotorc(struct ui_browser *browser, int y, int x) | 48 | void 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 | ||
53 | void 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 | |||
53 | void ui_browser__write_nstring(struct ui_browser *browser __maybe_unused, const char *msg, | 58 | void 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); | |||
38 | void ui_browser__refresh_dimensions(struct ui_browser *browser); | 39 | void ui_browser__refresh_dimensions(struct ui_browser *browser); |
39 | void ui_browser__reset_index(struct ui_browser *browser); | 40 | void ui_browser__reset_index(struct ui_browser *browser); |
40 | 41 | ||
42 | void ui_browser__gotorc_title(struct ui_browser *browser, int y, int x); | ||
41 | void ui_browser__gotorc(struct ui_browser *browser, int y, int x); | 43 | void ui_browser__gotorc(struct ui_browser *browser, int y, int x); |
42 | void ui_browser__write_nstring(struct ui_browser *browser, const char *msg, | 44 | void 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 | ||
595 | static 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 | |||
595 | static int annotate_browser__run(struct annotate_browser *browser, | 612 | static 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 | ||
33 | extern void hist_browser__init_hpp(void); | 33 | extern void hist_browser__init_hpp(void); |
34 | 34 | ||
35 | static int perf_evsel_browser_title(struct hist_browser *browser, | 35 | static int hists_browser__scnprintf_title(struct hist_browser *browser, char *bf, size_t size); |
36 | char *bf, size_t size); | ||
37 | static void hist_browser__update_nr_entries(struct hist_browser *hb); | 36 | static void hist_browser__update_nr_entries(struct hist_browser *hb); |
38 | 37 | ||
39 | static struct rb_node *hists__filter_entries(struct rb_node *nd, | 38 | static 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 | ||
64 | static 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 | |||
65 | static u32 hist_browser__nr_entries(struct hist_browser *hb) | 73 | static 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 | |||
114 | static 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 | ||
124 | static void hist_browser__reset(struct hist_browser *browser) | 127 | static 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) | |||
1740 | static unsigned int hist_browser__refresh(struct ui_browser *browser) | 1744 | static 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 | ||
1794 | static struct rb_node *hists__filter_entries(struct rb_node *nd, | 1792 | static 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 | ||
2212 | static int perf_evsel_browser_title(struct hist_browser *browser, | 2211 | static 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 | ||
2597 | int __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 | |||
151 | void annotation_line__write(struct annotation_line *al, struct annotation *notes, | 151 | void annotation_line__write(struct annotation_line *al, struct annotation *notes, |
152 | struct annotation_write_ops *ops); | 152 | struct annotation_write_ops *ops); |
153 | 153 | ||
154 | int __annotation__scnprintf_samples_period(struct annotation *notes, | ||
155 | char *bf, size_t size, | ||
156 | struct perf_evsel *evsel, | ||
157 | bool show_freq); | ||
158 | |||
159 | static 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 | |||
154 | int disasm_line__scnprintf(struct disasm_line *dl, char *bf, size_t size, bool raw); | 166 | int disasm_line__scnprintf(struct disasm_line *dl, char *bf, size_t size, bool raw); |
155 | size_t disasm__fprintf(struct list_head *head, FILE *fp); | 167 | size_t disasm__fprintf(struct list_head *head, FILE *fp); |
156 | void symbol__calc_percent(struct symbol *sym, struct perf_evsel *evsel); | 168 | void 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 | ||
305 | static 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 | |||
305 | static int auxtrace_queues__add_buffer(struct auxtrace_queues *queues, | 312 | static 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 | ||
339 | static bool filter_cpu(struct perf_session *session, int cpu) | 352 | out_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 | ||
346 | int auxtrace_queues__add_event(struct auxtrace_queues *queues, | 357 | int 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 | ||
378 | out_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 | ||
383 | static int auxtrace_queues__add_indexed_event(struct auxtrace_queues *queues, | 377 | static 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 | ||
19 | static bool hists__filter_entry_by_dso(struct hists *hists, | 21 | static 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 | ||
2459 | int __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 | |||
2457 | int parse_filter_percentage(const struct option *opt __maybe_unused, | 2538 | int 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, ...); | |||
503 | int __hist_entry__snprintf(struct hist_entry *he, struct perf_hpp *hpp, | 504 | int __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); |
505 | int hists__fprintf_headers(struct hists *hists, FILE *fp); | 506 | int hists__fprintf_headers(struct hists *hists, FILE *fp); |
507 | int __hists__scnprintf_title(struct hists *hists, char *bf, size_t size, bool show_freq); | ||
508 | |||
509 | static 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 | ||
106 | static 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=` */ |
108 | u64 map__rip_2objdump(struct map *map, u64 rip); | 112 | u64 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 | |||
1550 | static 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 | |||
1559 | static int64_t | ||
1560 | sort__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 | |||
1565 | static 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 | |||
1575 | static 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 | |||
1581 | struct 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 | ||
1549 | struct sort_dimension { | 1589 | struct 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 */ |
18 | void usage(const char *err) __noreturn; | 17 | void 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 | ||
28 | struct dirent; | 27 | struct dirent; |
28 | struct nsinfo; | ||
29 | struct strlist; | 29 | struct strlist; |
30 | 30 | ||
31 | int mkdir_p(char *path, mode_t mode); | 31 | int mkdir_p(char *path, mode_t mode); |