From: Stephane Eranian <eranian@google.com>
To: linux-kernel@vger.kernel.org
Cc: acme@redhat.com, peterz@infradead.org, mingo@elte.hu,
sukadev@linux.vnet.ibm.com, jolsa@redhat.com, dsahern@gmail.com,
ak@linux.intel.com
Subject: [PATCH] perf mem: add priv level filtering support
Date: Mon, 26 Aug 2013 15:11:21 +0200 [thread overview]
Message-ID: <20130826131121.GA26224@quad> (raw)
perf mem: add priv level filtering support
This patch adds the -u -and -k options to perf to allow
filtering of load/store sampling based on priv levels.
This may not be supported by all HW platforms.
By default, loads/stores are sampled at both user and
kernel privilege levels.
To sample only at the user level:
$ perf mem -u -t load rec ......
To sample only at the kernel level:
$ perf mem -k -t load rec ......
Man page updated accordingly.
Signed-off-by: Stephane Eranian <eranian@google.com>
---
diff --git a/tools/perf/Documentation/perf-mem.txt b/tools/perf/Documentation/perf-mem.txt
index 888d511..4c4e405 100644
--- a/tools/perf/Documentation/perf-mem.txt
+++ b/tools/perf/Documentation/perf-mem.txt
@@ -43,6 +43,12 @@ OPTIONS
option can be passed in record mode. It will be interpreted the same way as perf
record.
+-k::
+ Only sample loads/stores at the user level (default: user + kernel)
+
+-u::
+ Only sample loads/stores at the kernel level (default: user + kernel)
+
SEE ALSO
--------
linkperf:perf-record[1], linkperf:perf-report[1]
diff --git a/tools/perf/builtin-mem.c b/tools/perf/builtin-mem.c
index 706a1fa..8ac9d1e 100644
--- a/tools/perf/builtin-mem.c
+++ b/tools/perf/builtin-mem.c
@@ -9,13 +9,18 @@
#define MEM_OPERATION_LOAD "load"
#define MEM_OPERATION_STORE "store"
-static const char *mem_operation = MEM_OPERATION_LOAD;
+#define OP_LOAD 0x1
+#define OP_STORE 0x2
+
struct perf_mem {
struct perf_tool tool;
char const *input_name;
bool hide_unresolved;
+ const char *mem_op;
bool dump_raw;
+ bool user;
+ bool kernel;
const char *cpu_list;
DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS);
};
@@ -25,35 +30,88 @@ static const char * const mem_usage[] = {
NULL
};
-static int __cmd_record(int argc, const char **argv)
+static inline const char *get_plm(struct perf_mem *mem)
+{
+ const char *plm = "";
+
+ if (mem->user && !mem->kernel) {
+ plm = "u";
+ } else if (!mem->user && mem->kernel) {
+ plm = "k";
+ }
+ return plm;
+}
+
+static int __cmd_record(int argc, const char **argv, struct perf_mem *mem)
{
int rec_argc, i = 0, j;
const char **rec_argv;
- char event[64];
- int ret;
+ char *str;
+ int mode = 0;
+ int ki, ret;
+
+
+ if (!strcmp(mem->mem_op, MEM_OPERATION_STORE))
+ mode |= OP_STORE;
+ else if (!strcmp(mem->mem_op, MEM_OPERATION_LOAD))
+ mode |= OP_LOAD;
+ else {
+ fprintf(stderr, "unknown sampling mode: %s\n", mem->mem_op);
+ return -1;
+ }
- rec_argc = argc + 4;
+ rec_argc = argc + 6;
rec_argv = calloc(rec_argc + 1, sizeof(char *));
if (!rec_argv)
return -1;
rec_argv[i++] = strdup("record");
- if (!strcmp(mem_operation, MEM_OPERATION_LOAD))
- rec_argv[i++] = strdup("-W");
+
rec_argv[i++] = strdup("-d");
- rec_argv[i++] = strdup("-e");
- if (strcmp(mem_operation, MEM_OPERATION_LOAD))
- sprintf(event, "cpu/mem-stores/pp");
- else
- sprintf(event, "cpu/mem-loads/pp");
+ if (mode & OP_LOAD) {
+ rec_argv[i++] = strdup("-W");
- rec_argv[i++] = strdup(event);
- for (j = 1; j < argc; j++, i++)
- rec_argv[i] = argv[j];
+ rec_argv[i++] = strdup("-e");
+
+ str = malloc(strlen("cpu/mem-loads/pp") + 1 + 1);
+ if (!str) {
+ ki = i;
+ ret = -1;
+ goto end;
+ }
+ sprintf(str, "cpu/mem-loads/%spp", get_plm(mem));
+ rec_argv[i++] = str;
+ }
+
+ if (mode & OP_STORE) {
+ rec_argv[i++] = strdup("-e");
+
+ str = malloc(strlen("cpu/mem-stores/pp") + 1 + 1);
+ if (!str) {
+ ki = i;
+ ret = -1;
+ goto end;
+ }
+ sprintf(str, "cpu/mem-stores/%spp", get_plm(mem));
+ rec_argv[i++] = str;
+ }
+
+ /* arguments after i are not malloc'd */
+ ki = i;
- ret = cmd_record(i, rec_argv, NULL);
+ for (j = 1; j < argc; j++, ki++)
+ rec_argv[ki] = argv[j];
+
+ ret = cmd_record(ki, rec_argv, NULL);
+
+end:
+ /*
+ * XXX: free rec_argv[] entries, difficult because
+ * cmd_record() drops some of them...
+ */
free(rec_argv);
+
return ret;
}
@@ -171,7 +229,7 @@ static int report_events(int argc, const char **argv, struct perf_mem *mem)
* there is no weight (cost) associated with stores, so don't print
* the column
*/
- if (strcmp(mem_operation, MEM_OPERATION_LOAD))
+ if (strcmp(mem->mem_op, MEM_OPERATION_LOAD))
rep_argv[i++] = strdup("--sort=mem,sym,dso,symbol_daddr,"
"dso_daddr,tlb,locked");
@@ -199,7 +257,7 @@ int cmd_mem(int argc, const char **argv, const char *prefix __maybe_unused)
.input_name = "perf.data",
};
const struct option mem_options[] = {
- OPT_STRING('t', "type", &mem_operation,
+ OPT_STRING('t', "type", &mem.mem_op,
"type", "memory operations(load/store)"),
OPT_BOOLEAN('D', "dump-raw-samples", &mem.dump_raw,
"dump raw samples in ASCII"),
@@ -213,13 +271,18 @@ int cmd_mem(int argc, const char **argv, const char *prefix __maybe_unused)
"separator",
"separator for columns, no spaces will be added"
" between columns '.' is reserved."),
+ OPT_BOOLEAN('u', "user-level", &mem.user,
+ "include user-level accesses"),
+ OPT_BOOLEAN('k', "kernel-level", &mem.kernel,
+ "include kernel-level accesses"),
OPT_END()
};
argc = parse_options(argc, argv, mem_options, mem_usage,
PARSE_OPT_STOP_AT_NON_OPTION);
- if (!argc || !(strncmp(argv[0], "rec", 3) || mem_operation))
+ if (!argc || !(strncmp(argv[0], "rec", 3)
+ || strncmp(argv[0], "rep", 3)))
usage_with_options(mem_usage, mem_options);
if (!mem.input_name || !strlen(mem.input_name)) {
@@ -228,9 +291,12 @@ int cmd_mem(int argc, const char **argv, const char *prefix __maybe_unused)
else
mem.input_name = "perf.data";
}
+ /* default to load only, some processors only support loads */
+ if (!mem.mem_op)
+ mem.mem_op = MEM_OPERATION_LOAD;
if (!strncmp(argv[0], "rec", 3))
- return __cmd_record(argc, argv);
+ return __cmd_record(argc, argv, &mem);
else if (!strncmp(argv[0], "rep", 3))
return report_events(argc, argv, &mem);
else
next reply other threads:[~2013-08-26 13:10 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-08-26 13:11 Stephane Eranian [this message]
2013-08-26 22:21 ` [PATCH] perf mem: add priv level filtering support David Ahern
2013-08-28 13:20 ` Stephane Eranian
2013-08-28 13:27 ` Arnaldo Carvalho de Melo
2013-08-28 13:38 ` Stephane Eranian
2013-08-28 13:53 ` Stephane Eranian
2013-08-28 14:21 ` Arnaldo Carvalho de Melo
2013-09-06 0:15 ` Sukadev Bhattiprolu
2013-09-06 3:41 ` Andi Kleen
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=20130826131121.GA26224@quad \
--to=eranian@google.com \
--cc=acme@redhat.com \
--cc=ak@linux.intel.com \
--cc=dsahern@gmail.com \
--cc=jolsa@redhat.com \
--cc=linux-kernel@vger.kernel.org \
--cc=mingo@elte.hu \
--cc=peterz@infradead.org \
--cc=sukadev@linux.vnet.ibm.com \
/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