mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Arnaldo Carvalho de Melo <acme@kernel.org>
To: Ingo Molnar <mingo@kernel.org>
Cc: linux-kernel@vger.kernel.org,
	Adrian Hunter <adrian.hunter@intel.com>,
	David Ahern <dsahern@gmail.com>,
	Frederic Weisbecker <fweisbec@gmail.com>,
	Namhyung Kim <namhyung@gmail.com>,
	Peter Zijlstra <peterz@infradead.org>,
	Stephane Eranian <eranian@google.com>,
	Arnaldo Carvalho de Melo <acme@redhat.com>
Subject: [PATCH 16/64] perf auxtrace: Add support for AUX area recording
Date: Tue, 28 Apr 2015 10:30:08 -0300	[thread overview]
Message-ID: <1430227856-25825-17-git-send-email-acme@kernel.org> (raw)
In-Reply-To: <1430227856-25825-1-git-send-email-acme@kernel.org>

From: Adrian Hunter <adrian.hunter@intel.com>

Add support for reading from the AUX area tracing mmap and synthesizing
AUX area tracing events.

This patch introduces an abstraction for recording AUX area data.

Recording is initialized by auxtrace_record__init() which is a weak
function to be implemented by the architecture to provide recording
callbacks.

Recording is mainly handled by auxtrace_mmap__read() and
perf_event__synthesize_auxtrace() but there are callbacks for
miscellaneous needs including validating and processing user options,
populating private data in auxtrace_info_event, and freeing the
structure when finished.

Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
Acked-by: Jiri Olsa <jolsa@kernel.org>
Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Namhyung Kim <namhyung@gmail.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/r/1428594864-29309-5-git-send-email-adrian.hunter@intel.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/perf.h          |   2 +
 tools/perf/util/auxtrace.c | 176 +++++++++++++++++++++++++++++++++++++++++++++
 tools/perf/util/auxtrace.h |  56 ++++++++++++++-
 tools/perf/util/record.c   |  11 ++-
 4 files changed, 243 insertions(+), 2 deletions(-)

diff --git a/tools/perf/perf.h b/tools/perf/perf.h
index e14bb637255c..5042093d5213 100644
--- a/tools/perf/perf.h
+++ b/tools/perf/perf.h
@@ -54,8 +54,10 @@ struct record_opts {
 	bool	     period;
 	bool	     sample_intr_regs;
 	bool	     running_time;
+	bool	     full_auxtrace;
 	unsigned int freq;
 	unsigned int mmap_pages;
+	unsigned int auxtrace_mmap_pages;
 	unsigned int user_freq;
 	u64          branch_stack;
 	u64	     default_interval;
diff --git a/tools/perf/util/auxtrace.c b/tools/perf/util/auxtrace.c
index dedb64613000..2cafea2ec015 100644
--- a/tools/perf/util/auxtrace.c
+++ b/tools/perf/util/auxtrace.c
@@ -23,6 +23,10 @@
 #include <linux/bitops.h>
 #include <linux/log2.h>
 
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
 #include "../perf.h"
 #include "util.h"
 #include "evlist.h"
@@ -31,6 +35,9 @@
 #include "asm/bug.h"
 #include "auxtrace.h"
 
+#include "event.h"
+#include "debug.h"
+
 int auxtrace_mmap__mmap(struct auxtrace_mmap *mm,
 			struct auxtrace_mmap_params *mp,
 			void *userpg, int fd)
@@ -111,3 +118,172 @@ void auxtrace_mmap_params__set_idx(struct auxtrace_mmap_params *mp,
 		mp->tid = evlist->threads->map[idx];
 	}
 }
+
+size_t auxtrace_record__info_priv_size(struct auxtrace_record *itr)
+{
+	if (itr)
+		return itr->info_priv_size(itr);
+	return 0;
+}
+
+static int auxtrace_not_supported(void)
+{
+	pr_err("AUX area tracing is not supported on this architecture\n");
+	return -EINVAL;
+}
+
+int auxtrace_record__info_fill(struct auxtrace_record *itr,
+			       struct perf_session *session,
+			       struct auxtrace_info_event *auxtrace_info,
+			       size_t priv_size)
+{
+	if (itr)
+		return itr->info_fill(itr, session, auxtrace_info, priv_size);
+	return auxtrace_not_supported();
+}
+
+void auxtrace_record__free(struct auxtrace_record *itr)
+{
+	if (itr)
+		itr->free(itr);
+}
+
+int auxtrace_record__options(struct auxtrace_record *itr,
+			     struct perf_evlist *evlist,
+			     struct record_opts *opts)
+{
+	if (itr)
+		return itr->recording_options(itr, evlist, opts);
+	return 0;
+}
+
+u64 auxtrace_record__reference(struct auxtrace_record *itr)
+{
+	if (itr)
+		return itr->reference(itr);
+	return 0;
+}
+
+struct auxtrace_record *__weak
+auxtrace_record__init(struct perf_evlist *evlist __maybe_unused, int *err)
+{
+	*err = 0;
+	return NULL;
+}
+
+int perf_event__synthesize_auxtrace_info(struct auxtrace_record *itr,
+					 struct perf_tool *tool,
+					 struct perf_session *session,
+					 perf_event__handler_t process)
+{
+	union perf_event *ev;
+	size_t priv_size;
+	int err;
+
+	pr_debug2("Synthesizing auxtrace information\n");
+	priv_size = auxtrace_record__info_priv_size(itr);
+	ev = zalloc(sizeof(struct auxtrace_info_event) + priv_size);
+	if (!ev)
+		return -ENOMEM;
+
+	ev->auxtrace_info.header.type = PERF_RECORD_AUXTRACE_INFO;
+	ev->auxtrace_info.header.size = sizeof(struct auxtrace_info_event) +
+					priv_size;
+	err = auxtrace_record__info_fill(itr, session, &ev->auxtrace_info,
+					 priv_size);
+	if (err)
+		goto out_free;
+
+	err = process(tool, ev, NULL, NULL);
+out_free:
+	free(ev);
+	return err;
+}
+
+int auxtrace_mmap__read(struct auxtrace_mmap *mm, struct auxtrace_record *itr,
+			struct perf_tool *tool, process_auxtrace_t fn)
+{
+	u64 head = auxtrace_mmap__read_head(mm);
+	u64 old = mm->prev, offset, ref;
+	unsigned char *data = mm->base;
+	size_t size, head_off, old_off, len1, len2, padding;
+	union perf_event ev;
+	void *data1, *data2;
+
+	if (old == head)
+		return 0;
+
+	pr_debug3("auxtrace idx %d old %#"PRIx64" head %#"PRIx64" diff %#"PRIx64"\n",
+		  mm->idx, old, head, head - old);
+
+	if (mm->mask) {
+		head_off = head & mm->mask;
+		old_off = old & mm->mask;
+	} else {
+		head_off = head % mm->len;
+		old_off = old % mm->len;
+	}
+
+	if (head_off > old_off)
+		size = head_off - old_off;
+	else
+		size = mm->len - (old_off - head_off);
+
+	ref = auxtrace_record__reference(itr);
+
+	if (head > old || size <= head || mm->mask) {
+		offset = head - size;
+	} else {
+		/*
+		 * When the buffer size is not a power of 2, 'head' wraps at the
+		 * highest multiple of the buffer size, so we have to subtract
+		 * the remainder here.
+		 */
+		u64 rem = (0ULL - mm->len) % mm->len;
+
+		offset = head - size - rem;
+	}
+
+	if (size > head_off) {
+		len1 = size - head_off;
+		data1 = &data[mm->len - len1];
+		len2 = head_off;
+		data2 = &data[0];
+	} else {
+		len1 = size;
+		data1 = &data[head_off - len1];
+		len2 = 0;
+		data2 = NULL;
+	}
+
+	/* padding must be written by fn() e.g. record__process_auxtrace() */
+	padding = size & 7;
+	if (padding)
+		padding = 8 - padding;
+
+	memset(&ev, 0, sizeof(ev));
+	ev.auxtrace.header.type = PERF_RECORD_AUXTRACE;
+	ev.auxtrace.header.size = sizeof(ev.auxtrace);
+	ev.auxtrace.size = size + padding;
+	ev.auxtrace.offset = offset;
+	ev.auxtrace.reference = ref;
+	ev.auxtrace.idx = mm->idx;
+	ev.auxtrace.tid = mm->tid;
+	ev.auxtrace.cpu = mm->cpu;
+
+	if (fn(tool, &ev, data1, len1, data2, len2))
+		return -1;
+
+	mm->prev = head;
+
+	auxtrace_mmap__write_tail(mm, head);
+	if (itr->read_finish) {
+		int err;
+
+		err = itr->read_finish(itr, mm->idx);
+		if (err < 0)
+			return err;
+	}
+
+	return 1;
+}
diff --git a/tools/perf/util/auxtrace.h b/tools/perf/util/auxtrace.h
index 2071b36560a0..7ab4850703f0 100644
--- a/tools/perf/util/auxtrace.h
+++ b/tools/perf/util/auxtrace.h
@@ -18,13 +18,18 @@
 
 #include <sys/types.h>
 #include <stdbool.h>
-
+#include <stddef.h>
 #include <linux/perf_event.h>
 #include <linux/types.h>
 
 #include "../perf.h"
 
+union perf_event;
+struct perf_session;
 struct perf_evlist;
+struct perf_tool;
+struct record_opts;
+struct auxtrace_info_event;
 
 /**
  * struct auxtrace_mmap - records an mmap of the auxtrace buffer.
@@ -70,6 +75,29 @@ struct auxtrace_mmap_params {
 	int		cpu;
 };
 
+/**
+ * struct auxtrace_record - callbacks for recording AUX area data.
+ * @recording_options: validate and process recording options
+ * @info_priv_size: return the size of the private data in auxtrace_info_event
+ * @info_fill: fill-in the private data in auxtrace_info_event
+ * @free: free this auxtrace record structure
+ * @reference: provide a 64-bit reference number for auxtrace_event
+ * @read_finish: called after reading from an auxtrace mmap
+ */
+struct auxtrace_record {
+	int (*recording_options)(struct auxtrace_record *itr,
+				 struct perf_evlist *evlist,
+				 struct record_opts *opts);
+	size_t (*info_priv_size)(struct auxtrace_record *itr);
+	int (*info_fill)(struct auxtrace_record *itr,
+			 struct perf_session *session,
+			 struct auxtrace_info_event *auxtrace_info,
+			 size_t priv_size);
+	void (*free)(struct auxtrace_record *itr);
+	u64 (*reference)(struct auxtrace_record *itr);
+	int (*read_finish)(struct auxtrace_record *itr, int idx);
+};
+
 static inline u64 auxtrace_mmap__read_head(struct auxtrace_mmap *mm)
 {
 	struct perf_event_mmap_page *pc = mm->userpg;
@@ -114,4 +142,30 @@ void auxtrace_mmap_params__set_idx(struct auxtrace_mmap_params *mp,
 				   struct perf_evlist *evlist, int idx,
 				   bool per_cpu);
 
+typedef int (*process_auxtrace_t)(struct perf_tool *tool,
+				  union perf_event *event, void *data1,
+				  size_t len1, void *data2, size_t len2);
+
+int auxtrace_mmap__read(struct auxtrace_mmap *mm, struct auxtrace_record *itr,
+			struct perf_tool *tool, process_auxtrace_t fn);
+
+struct auxtrace_record *auxtrace_record__init(struct perf_evlist *evlist,
+					      int *err);
+
+int auxtrace_record__options(struct auxtrace_record *itr,
+			     struct perf_evlist *evlist,
+			     struct record_opts *opts);
+size_t auxtrace_record__info_priv_size(struct auxtrace_record *itr);
+int auxtrace_record__info_fill(struct auxtrace_record *itr,
+			       struct perf_session *session,
+			       struct auxtrace_info_event *auxtrace_info,
+			       size_t priv_size);
+void auxtrace_record__free(struct auxtrace_record *itr);
+u64 auxtrace_record__reference(struct auxtrace_record *itr);
+
+int perf_event__synthesize_auxtrace_info(struct auxtrace_record *itr,
+					 struct perf_tool *tool,
+					 struct perf_session *session,
+					 perf_event__handler_t process);
+
 #endif
diff --git a/tools/perf/util/record.c b/tools/perf/util/record.c
index 8acd0df88b5c..0ccfa498f7b8 100644
--- a/tools/perf/util/record.c
+++ b/tools/perf/util/record.c
@@ -119,7 +119,16 @@ void perf_evlist__config(struct perf_evlist *evlist, struct record_opts *opts)
 			evsel->attr.comm_exec = 1;
 	}
 
-	if (evlist->nr_entries > 1) {
+	if (opts->full_auxtrace) {
+		/*
+		 * Need to be able to synthesize and parse selected events with
+		 * arbitrary sample types, which requires always being able to
+		 * match the id.
+		 */
+		use_sample_identifier = perf_can_sample_identifier();
+		evlist__for_each(evlist, evsel)
+			perf_evsel__set_sample_id(evsel, use_sample_identifier);
+	} else if (evlist->nr_entries > 1) {
 		struct perf_evsel *first = perf_evlist__first(evlist);
 
 		evlist__for_each(evlist, evsel) {
-- 
1.9.3


  parent reply	other threads:[~2015-04-28 13:32 UTC|newest]

Thread overview: 65+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-04-28 13:29 [GIT PULL 00/64] perf/core improvements and fixes Arnaldo Carvalho de Melo
2015-04-28 13:29 ` [PATCH 01/64] perf hists: Get rid of position field from struct hist_entry Arnaldo Carvalho de Melo
2015-04-28 13:29 ` [PATCH 02/64] perf diff: Make hist_entry_diff fields union Arnaldo Carvalho de Melo
2015-04-28 13:29 ` [PATCH 03/64] perf data: Show error message when conversion failed Arnaldo Carvalho de Melo
2015-04-28 13:29 ` [PATCH 04/64] tools lib traceevent: Add alias field to struct format_field Arnaldo Carvalho de Melo
2015-04-28 13:29 ` [PATCH 05/64] tools build: No need to make libapi for perf explicitly Arnaldo Carvalho de Melo
2015-04-28 13:29 ` [PATCH 06/64] tools build: Fix Makefile(s) to properly invoke tools build Arnaldo Carvalho de Melo
2015-04-28 13:29 ` [PATCH 07/64] perf tests: Add build tests for building perf from kernel source root and tools Arnaldo Carvalho de Melo
2015-04-28 13:30 ` [PATCH 08/64] perf data: Switch to multiple cpu stream files Arnaldo Carvalho de Melo
2015-04-28 13:30 ` [PATCH 09/64] perf data: Enable stream flush within processing Arnaldo Carvalho de Melo
2015-04-28 13:30 ` [PATCH 10/64] perf data: Add support for setting ordered_events queue size Arnaldo Carvalho de Melo
2015-04-28 13:30 ` [PATCH 11/64] perf data: Fix duplicate field names and avoid reserved keywords Arnaldo Carvalho de Melo
2015-04-28 13:30 ` [PATCH 12/64] perf data: Fix signedness of value Arnaldo Carvalho de Melo
2015-04-28 13:30 ` [PATCH 13/64] perf header: Add AUX area tracing feature Arnaldo Carvalho de Melo
2015-04-28 13:30 ` [PATCH 14/64] perf evlist: Add support for mmapping an AUX area buffer Arnaldo Carvalho de Melo
2015-04-28 13:30 ` [PATCH 15/64] perf tools: Add user events for AUX area tracing Arnaldo Carvalho de Melo
2015-04-28 13:30 ` Arnaldo Carvalho de Melo [this message]
2015-04-28 13:30 ` [PATCH 17/64] perf record: Add basic AUX area tracing support Arnaldo Carvalho de Melo
2015-04-28 13:30 ` [PATCH 18/64] perf record: Extend -m option for AUX area tracing mmap pages Arnaldo Carvalho de Melo
2015-04-28 13:30 ` [PATCH 19/64] perf tools: Add a user event for AUX area tracing errors Arnaldo Carvalho de Melo
2015-04-28 13:30 ` [PATCH 20/64] perf session: Add hooks to allow transparent decoding of AUX area tracing data Arnaldo Carvalho de Melo
2015-04-28 13:30 ` [PATCH 21/64] perf session: Add instruction tracing options Arnaldo Carvalho de Melo
2015-04-28 13:30 ` [PATCH 22/64] perf auxtrace: Add helpers for AUX area tracing errors Arnaldo Carvalho de Melo
2015-04-28 13:30 ` [PATCH 23/64] perf auxtrace: Add helpers for queuing AUX area tracing data Arnaldo Carvalho de Melo
2015-04-28 13:30 ` [PATCH 24/64] perf auxtrace: Add a heap for sorting AUX area tracing queues Arnaldo Carvalho de Melo
2015-04-28 13:30 ` [PATCH 25/64] perf auxtrace: Add processing for AUX area tracing events Arnaldo Carvalho de Melo
2015-04-28 13:30 ` [PATCH 26/64] perf auxtrace: Add a hashtable for caching Arnaldo Carvalho de Melo
2015-04-28 13:30 ` [PATCH 27/64] perf tools: Add member to struct dso for an instruction cache Arnaldo Carvalho de Melo
2015-04-28 13:30 ` [PATCH 28/64] perf script: Add Instruction Tracing support Arnaldo Carvalho de Melo
2015-04-28 13:30 ` [PATCH 29/64] perf inject: Re-pipe AUX area tracing events Arnaldo Carvalho de Melo
2015-04-28 13:30 ` [PATCH 30/64] perf inject: Add Instruction Tracing support Arnaldo Carvalho de Melo
2015-04-28 13:30 ` [PATCH 31/64] perf script: Add field option 'flags' to print sample flags Arnaldo Carvalho de Melo
2015-04-28 13:30 ` [PATCH 32/64] perf tools: Add aux_watermark member of struct perf_event_attr Arnaldo Carvalho de Melo
2015-04-28 13:30 ` [PATCH 33/64] perf tools: Add parse_events_error interface Arnaldo Carvalho de Melo
2015-04-28 13:30 ` [PATCH 34/64] perf tools: Add flex support for parse_events_error Arnaldo Carvalho de Melo
2015-04-28 13:30 ` [PATCH 35/64] perf tools: Always bail out when config_attr function fails Arnaldo Carvalho de Melo
2015-04-28 13:30 ` [PATCH 36/64] perf tools: Change parse_events_add_pmu interface Arnaldo Carvalho de Melo
2015-04-28 13:30 ` [PATCH 37/64] perf tools: Add location to pmu event terms Arnaldo Carvalho de Melo
2015-04-28 13:30 ` [PATCH 38/64] perf tools: Add term support for parse_events_error Arnaldo Carvalho de Melo
2015-04-28 13:30 ` [PATCH 39/64] perf tools: Add static terms " Arnaldo Carvalho de Melo
2015-04-28 13:30 ` [PATCH 40/64] perf tools: Add tracepoint " Arnaldo Carvalho de Melo
2015-04-28 13:30 ` [PATCH 41/64] perf tools: Add symbolic events " Arnaldo Carvalho de Melo
2015-04-28 13:30 ` [PATCH 42/64] perf probe: Make --funcs option exclusive Arnaldo Carvalho de Melo
2015-04-28 13:30 ` [PATCH 43/64] perf probe: Remove all probes matches given pattern at once Arnaldo Carvalho de Melo
2015-04-28 13:30 ` [PATCH 44/64] perf trace: Fix --filter-pids OPTION description Arnaldo Carvalho de Melo
2015-04-28 13:30 ` [PATCH 45/64] perf trace: Clarify that -e is about syscalls, not perf events in general Arnaldo Carvalho de Melo
2015-04-28 13:30 ` [PATCH 46/64] perf stat: Fix metrics calculation with event qualifiers Arnaldo Carvalho de Melo
2015-04-28 13:30 ` [PATCH 47/64] perf stat: Change metrics context calculation Arnaldo Carvalho de Melo
2015-04-28 13:30 ` [PATCH 48/64] perf stat: Add metrics support for exclude_hv Arnaldo Carvalho de Melo
2015-04-28 13:30 ` [PATCH 49/64] perf stat: Add metrics support for exclude_(host|guest) Arnaldo Carvalho de Melo
2015-04-28 13:30 ` [PATCH 50/64] perf stat: Add metrics support for exclude_idle Arnaldo Carvalho de Melo
2015-04-28 13:30 ` [PATCH 51/64] perf tools: Document --children option in more detail Arnaldo Carvalho de Melo
2015-04-28 13:30 ` [PATCH 52/64] perf tools: Move TUI-specific fields into unnamed union Arnaldo Carvalho de Melo
2015-04-28 13:30 ` [PATCH 53/64] perf tools: Move init_have_children field to the " Arnaldo Carvalho de Melo
2015-04-28 13:30 ` [PATCH 54/64] perf hists browser: Fix possible memory leak Arnaldo Carvalho de Melo
2015-04-28 13:30 ` [PATCH 55/64] perf hists browser: Save hist_browser_timer pointer in hist_browser Arnaldo Carvalho de Melo
2015-04-28 13:30 ` [PATCH 56/64] perf hists browser: Save pstack in the hist_browser Arnaldo Carvalho de Melo
2015-04-28 13:30 ` [PATCH 57/64] perf hists browser: Save perf_session_env " Arnaldo Carvalho de Melo
2015-04-28 13:30 ` [PATCH 58/64] perf hists browser: Split popup menu actions Arnaldo Carvalho de Melo
2015-04-28 13:30 ` [PATCH 59/64] perf hists browser: Split popup menu actions - part 2 Arnaldo Carvalho de Melo
2015-04-28 13:30 ` [PATCH 60/64] perf tools: Introduce pstack_peek() Arnaldo Carvalho de Melo
2015-04-28 13:30 ` [PATCH 61/64] perf hists browser: Simplify zooming code using pstack_peek() Arnaldo Carvalho de Melo
2015-04-28 13:30 ` [PATCH 62/64] perf tools: Move TUI-specific fields out of map_symbol Arnaldo Carvalho de Melo
2015-04-28 13:30 ` [PATCH 63/64] perf tools: Use getconf to determine number of online CPUs Arnaldo Carvalho de Melo
2015-04-28 13:30 ` [PATCH 64/64] perf bench numa: Show more stats of particular threads in verbose mode Arnaldo Carvalho de Melo

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1430227856-25825-17-git-send-email-acme@kernel.org \
    --to=acme@kernel.org \
    --cc=acme@redhat.com \
    --cc=adrian.hunter@intel.com \
    --cc=dsahern@gmail.com \
    --cc=eranian@google.com \
    --cc=fweisbec@gmail.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mingo@kernel.org \
    --cc=namhyung@gmail.com \
    --cc=peterz@infradead.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

Powered by JetHome