From 0d75f123a6dcdacb3550b0c3c44a283f7259289e Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Tue, 6 Mar 2018 11:13:17 +0200 Subject: [PATCH 1/6] perf auxtrace: Make auxtrace_queues__add_buffer() allocate struct buffer In preparation for supporting AUX area sampling buffers, auxtrace_queues__add_buffer() needs to be more generic. To that end, move memory allocation for struct buffer into it. Signed-off-by: Adrian Hunter Cc: Jiri Olsa Link: http://lkml.kernel.org/r/1520327598-1317-7-git-send-email-adrian.hunter@intel.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/auxtrace.c | 54 +++++++++++++++++--------------------- 1 file changed, 24 insertions(+), 30 deletions(-) diff --git a/tools/perf/util/auxtrace.c b/tools/perf/util/auxtrace.c index fb357a00dd868..e1aff91c54a88 100644 --- a/tools/perf/util/auxtrace.c +++ b/tools/perf/util/auxtrace.c @@ -308,7 +308,11 @@ static int auxtrace_queues__add_buffer(struct auxtrace_queues *queues, struct auxtrace_buffer *buffer, struct auxtrace_buffer **buffer_ptr) { - int err; + int err = -ENOMEM; + + buffer = memdup(buffer, sizeof(*buffer)); + if (!buffer) + return -ENOMEM; if (session->one_mmap) { buffer->data = buffer->data_offset - session->one_mmap_offset + @@ -316,24 +320,28 @@ static int auxtrace_queues__add_buffer(struct auxtrace_queues *queues, } else if (perf_data__is_pipe(session->data)) { buffer->data = auxtrace_copy_data(buffer->size, session); if (!buffer->data) - return -ENOMEM; + goto out_free; buffer->data_needs_freeing = true; } else if (BITS_PER_LONG == 32 && buffer->size > BUFFER_LIMIT_FOR_32_BIT) { err = auxtrace_queues__split_buffer(queues, idx, buffer); if (err) - return err; + goto out_free; } err = auxtrace_queues__queue_buffer(queues, idx, buffer); if (err) - return err; + goto out_free; /* FIXME: Doesn't work for split buffer */ if (buffer_ptr) *buffer_ptr = buffer; return 0; + +out_free: + auxtrace_buffer__free(buffer); + return err; } static bool filter_cpu(struct perf_session *session, int cpu) @@ -348,36 +356,22 @@ int auxtrace_queues__add_event(struct auxtrace_queues *queues, union perf_event *event, off_t data_offset, struct auxtrace_buffer **buffer_ptr) { - struct auxtrace_buffer *buffer; - unsigned int idx; - int err; + struct auxtrace_buffer buffer = { + .pid = -1, + .tid = event->auxtrace.tid, + .cpu = event->auxtrace.cpu, + .data_offset = data_offset, + .offset = event->auxtrace.offset, + .reference = event->auxtrace.reference, + .size = event->auxtrace.size, + }; + unsigned int idx = event->auxtrace.idx; if (filter_cpu(session, event->auxtrace.cpu)) return 0; - buffer = zalloc(sizeof(struct auxtrace_buffer)); - if (!buffer) - return -ENOMEM; - - buffer->pid = -1; - buffer->tid = event->auxtrace.tid; - buffer->cpu = event->auxtrace.cpu; - buffer->data_offset = data_offset; - buffer->offset = event->auxtrace.offset; - buffer->reference = event->auxtrace.reference; - buffer->size = event->auxtrace.size; - idx = event->auxtrace.idx; - - err = auxtrace_queues__add_buffer(queues, session, idx, buffer, - buffer_ptr); - if (err) - goto out_err; - - return 0; - -out_err: - auxtrace_buffer__free(buffer); - return err; + return auxtrace_queues__add_buffer(queues, session, idx, &buffer, + buffer_ptr); } static int auxtrace_queues__add_indexed_event(struct auxtrace_queues *queues, From c0459a092509f9c2ff91cc070cd2645d38e7cf7b Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Thu, 5 Apr 2018 11:13:24 -0300 Subject: [PATCH 2/6] perf annotate: Show group details on the title line MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit To match what is shown in the main 'perf report/top' title lines, i.e. if a group is being shown, either a real group (recorded with "-e '{a,b,c}') or a forced group (using 'perf report --group' for a perf.data file recorded without {}) we will show multiple columns, one per event, but we were failing to show the group details, so, for: # perf report --header-only | grep cmdline # cmdline : /home/acme/bin/perf record -e {cycles,instructions,cache-misses} # perf report --group The first line was showing just "cycles", now it shows the correct line, which is: Samples: 578 of events 'anon group { cycles, instructions, cache-misses }', 4000 Hz, Event count (approx.): 487421794 syscall_return_via_sysret /lib/modules/4.16.0-rc7/build/vmlinux 0.22 2.97 0.00 │ ↓ jmp 6c │ mov %cr3,%rdi 1.33 10.89 4.00 │ ↓ jmp 62 │ mov %rdi,%rax Cc: Adrian Hunter Cc: Andi Kleen Cc: David Ahern Cc: Jin Yao Cc: Jiri Olsa Cc: Namhyung Kim Cc: Wang Nan Fixes: 6920e2854e9a ("perf annotate browser: Show extra title line with event information") Link: https://lkml.kernel.org/n/tip-i41tqh17c2dabnyzjh99r1oz@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/annotate.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c index fffe16af9797c..fbad8dfbb186f 100644 --- a/tools/perf/util/annotate.c +++ b/tools/perf/util/annotate.c @@ -2600,7 +2600,7 @@ int __annotation__scnprintf_samples_period(struct annotation *notes, bool show_freq) { const char *ev_name = perf_evsel__name(evsel); - char ref[30] = " show reference callgraph, "; + char buf[1024], ref[30] = " show reference callgraph, "; char sample_freq_str[64] = ""; unsigned long nr_samples = 0; int nr_members = 1; @@ -2609,8 +2609,11 @@ int __annotation__scnprintf_samples_period(struct annotation *notes, char unit; int i; - if (perf_evsel__is_group_event(evsel)) + if (perf_evsel__is_group_event(evsel)) { + perf_evsel__group_desc(evsel, buf, sizeof(buf)); + ev_name = buf; nr_members = evsel->nr_members; + } for (i = 0; i < nr_members; i++) { struct sym_hist *ah = annotation__histogram(notes, evsel->idx + i); From e726c8511c052ba40dc943517b54011e42c2dfa3 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Thu, 5 Apr 2018 11:35:32 -0300 Subject: [PATCH 3/6] perf annotate browser: Fixup vertical line separating metrics from instructions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now that we can have extra title lines we should use ui_browser->rows and not ->height when drawing lines, as it will use ui_browser__gotorc() and that will take the extra title lines into account, which was causing an off by one at the end of the vertical line drawn by __ui_browser__vline(), fix it. The visual effect was that the last line, with status messages, was being overwritten by the vertical line, looking like: Press 'h' for help on│key bindings Cc: Adrian Hunter Cc: Andi Kleen Cc: David Ahern Cc: Jin Yao Cc: Jiri Olsa Cc: Namhyung Kim Cc: Wang Nan Fixes: ef9ff6017e3c ("perf ui browser: Move the extra title lines from the hists browser") Link: https://lkml.kernel.org/n/tip-08y1ln3xjn76zvizz1i1dsvn@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/ui/browsers/annotate.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/perf/ui/browsers/annotate.c b/tools/perf/ui/browsers/annotate.c index 78bcd220f1b66..12c099a87f8ba 100644 --- a/tools/perf/ui/browsers/annotate.c +++ b/tools/perf/ui/browsers/annotate.c @@ -218,7 +218,7 @@ static unsigned int annotate_browser__refresh(struct ui_browser *browser) annotate_browser__draw_current_jump(browser); ui_browser__set_color(browser, HE_COLORSET_NORMAL); - __ui_browser__vline(browser, pcnt_width, 0, browser->height - 1); + __ui_browser__vline(browser, pcnt_width, 0, browser->rows - 1); return ret; } From caf61de356189f0925b23c3922bd16b53bb7c768 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Thu, 5 Apr 2018 11:43:38 -0300 Subject: [PATCH 4/6] perf ui browser: Fixup cleaning unused lines at the bottom Now that we can have extra title lines we should use ui_browser->rows and not ->height when drawing lines, as well as adding ui_browser->extra_title_lines to browser->y when cleaning unused lines at the bottom, otherwise we end up clobbering with spaces the last line just shown by ui_browser->refresh() routine. Cc: Adrian Hunter Cc: Andi Kleen Cc: David Ahern Cc: Jin Yao Cc: Jiri Olsa Cc: Namhyung Kim Cc: Wang Nan Fixes: ef9ff6017e3c ("perf ui browser: Move the extra title lines from the hists browser") Link: https://lkml.kernel.org/n/tip-dfcpokt1pm5ixm8n9pxwtstz@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/ui/browser.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/perf/ui/browser.c b/tools/perf/ui/browser.c index d7bb2591838e9..4f75561424eda 100644 --- a/tools/perf/ui/browser.c +++ b/tools/perf/ui/browser.c @@ -343,8 +343,8 @@ static int __ui_browser__refresh(struct ui_browser *browser) else width += 1; - SLsmg_fill_region(browser->y + row, browser->x, - browser->height - row, width, ' '); + SLsmg_fill_region(browser->y + row + browser->extra_title_lines, browser->x, + browser->rows - row, width, ' '); return 0; } From 41a43dacecdbc9aec9d307bd9f6aa5ec16d65832 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Thu, 5 Apr 2018 14:34:09 -0300 Subject: [PATCH 5/6] perf report: Remove duplicated 'samples' in lost samples warning The following message, emitted when samples are lost due to system overload, had one 'samples' too many, ditch it: Processed 25333 samples and lost 20.88% samples! Cc: Adrian Hunter Cc: David Ahern Cc: Jiri Olsa Cc: Namhyung Kim Cc: Wang Nan Cc: Kan Liang Link: https://lkml.kernel.org/n/tip-oev1469y02hmfere6r2kkxp6@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/session.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index c71ced7db152e..f4a7a437ee87a 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -1591,7 +1591,7 @@ static void perf_session__warn_about_errors(const struct perf_session *session) drop_rate = (double)stats->total_lost_samples / (double) (stats->nr_events[PERF_RECORD_SAMPLE] + stats->total_lost_samples); if (drop_rate > 0.05) { - ui__warning("Processed %" PRIu64 " samples and lost %3.2f%% samples!\n\n", + ui__warning("Processed %" PRIu64 " samples and lost %3.2f%%!\n\n", stats->nr_events[PERF_RECORD_SAMPLE] + stats->total_lost_samples, drop_rate * 100.0); } From 01f97511f13cbf2ba3d23b2bffa06258dc81e283 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Thu, 5 Apr 2018 14:40:44 -0300 Subject: [PATCH 6/6] tools headers uapi: Synchronize i915_drm.h To pick up the changes in: c822e0591855 drm/i915: expose rcs topology through query uAPI a446ae2c6e65 drm/i915: add query uAPI This affects 'perf trace', that automagically gets the definition of the new I915_QUERY DRM ioctl: --- /tmp/build/perf/trace/beauty/generated/ioctl/drm_ioctl_array.c.old 2018-04-05 14:38:33.660111995 -0300 +++ /tmp/build/perf/trace/beauty/generated/ioctl/drm_ioctl_array.c 2018-04-05 14:40:17.923283914 -0300 @@ -158,4 +158,5 @@ [DRM_COMMAND_BASE + 0x36] = "I915_PERF_OPEN", [DRM_COMMAND_BASE + 0x37] = "I915_PERF_ADD_CONFIG", [DRM_COMMAND_BASE + 0x38] = "I915_PERF_REMOVE_CONFIG", + [DRM_COMMAND_BASE + 0x39] = "I915_QUERY", }; I.e. on systems where this is used it will appear when, for instance, one does a system wide 'perf trace' session looking for ioctl calls, just like it does with the previously implemented DRM_I915 ioctls: # perf trace -e ioctl --filter-pids 2190 4346.232 ( 0.012 ms): gnome-shell/1455 ioctl(fd: 8, cmd: DRM_I915_GEM_BUSY, arg: 0x7fff3b0cd910) = 0 4346.246 ( 0.002 ms): gnome-shell/1455 ioctl(fd: 8, cmd: DRM_I915_GEM_MADVISE, arg: 0x7fff3b0cd980) = 0 4346.252 ( 0.002 ms): gnome-shell/1455 ioctl(fd: 8, cmd: DRM_I915_GEM_BUSY, arg: 0x7fff3b0cdb00) = 0 This silences this perf tools build warning: Warning: Kernel ABI header at 'tools/include/uapi/drm/i915_drm.h' differs from latest version at 'include/uapi/drm/i915_drm.h' Cc: Adrian Hunter Cc: Chris Wilson Cc: David Ahern Cc: Jiri Olsa Cc: Joonas Lahtinen Cc: Lionel Landwerlin Cc: Namhyung Kim Cc: Tvrtko Ursulin Cc: Wang Nan Link: https://lkml.kernel.org/n/tip-5kxuvruuzdbojvf90f8j2wat@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/include/uapi/drm/i915_drm.h | 112 ++++++++++++++++++++++++++++-- 1 file changed, 108 insertions(+), 4 deletions(-) diff --git a/tools/include/uapi/drm/i915_drm.h b/tools/include/uapi/drm/i915_drm.h index 536ee4febd746..7f5634ce8e885 100644 --- a/tools/include/uapi/drm/i915_drm.h +++ b/tools/include/uapi/drm/i915_drm.h @@ -318,6 +318,7 @@ typedef struct _drm_i915_sarea { #define DRM_I915_PERF_OPEN 0x36 #define DRM_I915_PERF_ADD_CONFIG 0x37 #define DRM_I915_PERF_REMOVE_CONFIG 0x38 +#define DRM_I915_QUERY 0x39 #define DRM_IOCTL_I915_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t) #define DRM_IOCTL_I915_FLUSH DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLUSH) @@ -375,6 +376,7 @@ typedef struct _drm_i915_sarea { #define DRM_IOCTL_I915_PERF_OPEN DRM_IOW(DRM_COMMAND_BASE + DRM_I915_PERF_OPEN, struct drm_i915_perf_open_param) #define DRM_IOCTL_I915_PERF_ADD_CONFIG DRM_IOW(DRM_COMMAND_BASE + DRM_I915_PERF_ADD_CONFIG, struct drm_i915_perf_oa_config) #define DRM_IOCTL_I915_PERF_REMOVE_CONFIG DRM_IOW(DRM_COMMAND_BASE + DRM_I915_PERF_REMOVE_CONFIG, __u64) +#define DRM_IOCTL_I915_QUERY DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_QUERY, struct drm_i915_query) /* Allow drivers to submit batchbuffers directly to hardware, relying * on the security mechanisms provided by hardware. @@ -1358,7 +1360,9 @@ struct drm_intel_overlay_attrs { * active on a given plane. */ -#define I915_SET_COLORKEY_NONE (1<<0) /* disable color key matching */ +#define I915_SET_COLORKEY_NONE (1<<0) /* Deprecated. Instead set + * flags==0 to disable colorkeying. + */ #define I915_SET_COLORKEY_DESTINATION (1<<1) #define I915_SET_COLORKEY_SOURCE (1<<2) struct drm_intel_sprite_colorkey { @@ -1604,15 +1608,115 @@ struct drm_i915_perf_oa_config { __u32 n_flex_regs; /* - * These fields are pointers to tuples of u32 values (register - * address, value). For example the expected length of the buffer - * pointed by mux_regs_ptr is (2 * sizeof(u32) * n_mux_regs). + * These fields are pointers to tuples of u32 values (register address, + * value). For example the expected length of the buffer pointed by + * mux_regs_ptr is (2 * sizeof(u32) * n_mux_regs). */ __u64 mux_regs_ptr; __u64 boolean_regs_ptr; __u64 flex_regs_ptr; }; +struct drm_i915_query_item { + __u64 query_id; +#define DRM_I915_QUERY_TOPOLOGY_INFO 1 + + /* + * When set to zero by userspace, this is filled with the size of the + * data to be written at the data_ptr pointer. The kernel sets this + * value to a negative value to signal an error on a particular query + * item. + */ + __s32 length; + + /* + * Unused for now. Must be cleared to zero. + */ + __u32 flags; + + /* + * Data will be written at the location pointed by data_ptr when the + * value of length matches the length of the data to be written by the + * kernel. + */ + __u64 data_ptr; +}; + +struct drm_i915_query { + __u32 num_items; + + /* + * Unused for now. Must be cleared to zero. + */ + __u32 flags; + + /* + * This points to an array of num_items drm_i915_query_item structures. + */ + __u64 items_ptr; +}; + +/* + * Data written by the kernel with query DRM_I915_QUERY_TOPOLOGY_INFO : + * + * data: contains the 3 pieces of information : + * + * - the slice mask with one bit per slice telling whether a slice is + * available. The availability of slice X can be queried with the following + * formula : + * + * (data[X / 8] >> (X % 8)) & 1 + * + * - the subslice mask for each slice with one bit per subslice telling + * whether a subslice is available. The availability of subslice Y in slice + * X can be queried with the following formula : + * + * (data[subslice_offset + + * X * subslice_stride + + * Y / 8] >> (Y % 8)) & 1 + * + * - the EU mask for each subslice in each slice with one bit per EU telling + * whether an EU is available. The availability of EU Z in subslice Y in + * slice X can be queried with the following formula : + * + * (data[eu_offset + + * (X * max_subslices + Y) * eu_stride + + * Z / 8] >> (Z % 8)) & 1 + */ +struct drm_i915_query_topology_info { + /* + * Unused for now. Must be cleared to zero. + */ + __u16 flags; + + __u16 max_slices; + __u16 max_subslices; + __u16 max_eus_per_subslice; + + /* + * Offset in data[] at which the subslice masks are stored. + */ + __u16 subslice_offset; + + /* + * Stride at which each of the subslice masks for each slice are + * stored. + */ + __u16 subslice_stride; + + /* + * Offset in data[] at which the EU masks are stored. + */ + __u16 eu_offset; + + /* + * Stride at which each of the EU masks for each subslice are stored. + */ + __u16 eu_stride; + + __u8 data[]; +}; + #if defined(__cplusplus) } #endif