summaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorPu Hou <bjhoupu@linux.vnet.ibm.com>2016-09-01 10:48:22 +0200
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2017-11-16 15:06:08 +0100
commita3f22d505f56bf3efd8eecd9b7adcc40a40a4a8e (patch)
tree372ccfd4273a80b6e817b85efc6e9a02de502a1e /tools
parentcbf6948f36afcbeca61ed5c3d5e7d930567a200f (diff)
downloadlinux-a3f22d505f56bf3efd8eecd9b7adcc40a40a4a8e.tar.bz2
s390/perf: add callback to perf to enable using AUX buffer
Perf tool need implement a callback to enable using AUX buffer. Perf will do another mmap() to trigger the setup of AUX buffer in kernel if there is such callback. The default size of the AUX buffer is set properly according to the sampling frequency to avoid overflow. It could also be manually set by -m option of perf. The interface of perf is not changed. Diagnostic mode sampling could be started by `perf record -e rBD000` like before. Signed-off-by: Pu Hou <bjhoupu@linux.vnet.ibm.com> Reviewed-by: Hendrik Brueckner <brueckner@linux.vnet.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'tools')
-rw-r--r--tools/perf/arch/s390/util/Build2
-rw-r--r--tools/perf/arch/s390/util/auxtrace.c118
2 files changed, 120 insertions, 0 deletions
diff --git a/tools/perf/arch/s390/util/Build b/tools/perf/arch/s390/util/Build
index 5bd7b9260cc0..397084382b23 100644
--- a/tools/perf/arch/s390/util/Build
+++ b/tools/perf/arch/s390/util/Build
@@ -4,3 +4,5 @@ libperf-y += kvm-stat.o
libperf-$(CONFIG_DWARF) += dwarf-regs.o
libperf-y += machine.o
+
+libperf-$(CONFIG_AUXTRACE) += auxtrace.o
diff --git a/tools/perf/arch/s390/util/auxtrace.c b/tools/perf/arch/s390/util/auxtrace.c
new file mode 100644
index 000000000000..6cb48e4cffd9
--- /dev/null
+++ b/tools/perf/arch/s390/util/auxtrace.c
@@ -0,0 +1,118 @@
+#include <stdbool.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/bitops.h>
+#include <linux/log2.h>
+
+#include "../../util/evlist.h"
+#include "../../util/auxtrace.h"
+#include "../../util/evsel.h"
+
+#define PERF_EVENT_CPUM_SF 0xB0000 /* Event: Basic-sampling */
+#define PERF_EVENT_CPUM_SF_DIAG 0xBD000 /* Event: Combined-sampling */
+#define DEFAULT_AUX_PAGES 128
+#define DEFAULT_FREQ 4000
+
+static void cpumsf_free(struct auxtrace_record *itr)
+{
+ free(itr);
+}
+
+static size_t cpumsf_info_priv_size(struct auxtrace_record *itr __maybe_unused,
+ struct perf_evlist *evlist __maybe_unused)
+{
+ return 0;
+}
+
+static int
+cpumsf_info_fill(struct auxtrace_record *itr __maybe_unused,
+ struct perf_session *session __maybe_unused,
+ struct auxtrace_info_event *auxtrace_info __maybe_unused,
+ size_t priv_size __maybe_unused)
+{
+ return 0;
+}
+
+static unsigned long
+cpumsf_reference(struct auxtrace_record *itr __maybe_unused)
+{
+ return 0;
+}
+
+static int
+cpumsf_recording_options(struct auxtrace_record *ar __maybe_unused,
+ struct perf_evlist *evlist __maybe_unused,
+ struct record_opts *opts)
+{
+ unsigned int factor = 1;
+ unsigned int pages;
+
+ opts->full_auxtrace = true;
+
+ /*
+ * The AUX buffer size should be set properly to avoid
+ * overflow of samples if it is not set explicitly.
+ * DEFAULT_AUX_PAGES is an proper size when sampling frequency
+ * is DEFAULT_FREQ. It is expected to hold about 1/2 second
+ * of sampling data. The size used for AUX buffer will scale
+ * according to the specified frequency and DEFAULT_FREQ.
+ */
+ if (!opts->auxtrace_mmap_pages) {
+ if (opts->user_freq != UINT_MAX)
+ factor = (opts->user_freq + DEFAULT_FREQ
+ - 1) / DEFAULT_FREQ;
+ pages = DEFAULT_AUX_PAGES * factor;
+ opts->auxtrace_mmap_pages = roundup_pow_of_two(pages);
+ }
+
+ return 0;
+}
+
+static int
+cpumsf_parse_snapshot_options(struct auxtrace_record *itr __maybe_unused,
+ struct record_opts *opts __maybe_unused,
+ const char *str __maybe_unused)
+{
+ return 0;
+}
+
+/*
+ * auxtrace_record__init is called when perf record
+ * check if the event really need auxtrace
+ */
+struct auxtrace_record *auxtrace_record__init(struct perf_evlist *evlist,
+ int *err)
+{
+ struct auxtrace_record *aux;
+ struct perf_evsel *pos;
+ int diagnose = 0;
+
+ if (evlist->nr_entries == 0)
+ return NULL;
+
+ evlist__for_each_entry(evlist, pos) {
+ if (pos->attr.config == PERF_EVENT_CPUM_SF_DIAG) {
+ diagnose = 1;
+ break;
+ }
+ }
+
+ if (!diagnose)
+ return NULL;
+
+ /* sampling in diagnose mode. alloc aux buffer */
+ aux = zalloc(sizeof(*aux));
+ if (aux == NULL) {
+ *err = -ENOMEM;
+ return NULL;
+ }
+
+ aux->parse_snapshot_options = cpumsf_parse_snapshot_options;
+ aux->recording_options = cpumsf_recording_options;
+ aux->info_priv_size = cpumsf_info_priv_size;
+ aux->info_fill = cpumsf_info_fill;
+ aux->free = cpumsf_free;
+ aux->reference = cpumsf_reference;
+
+ return aux;
+}