diff options
Diffstat (limited to 'tools/perf/builtin-mem.c')
-rw-r--r-- | tools/perf/builtin-mem.c | 84 |
1 files changed, 76 insertions, 8 deletions
diff --git a/tools/perf/builtin-mem.c b/tools/perf/builtin-mem.c index 390170041696..88aeac9aa1da 100644 --- a/tools/perf/builtin-mem.c +++ b/tools/perf/builtin-mem.c | |||
@@ -6,6 +6,8 @@ | |||
6 | #include "util/tool.h" | 6 | #include "util/tool.h" |
7 | #include "util/session.h" | 7 | #include "util/session.h" |
8 | #include "util/data.h" | 8 | #include "util/data.h" |
9 | #include "util/mem-events.h" | ||
10 | #include "util/debug.h" | ||
9 | 11 | ||
10 | #define MEM_OPERATION_LOAD 0x1 | 12 | #define MEM_OPERATION_LOAD 0x1 |
11 | #define MEM_OPERATION_STORE 0x2 | 13 | #define MEM_OPERATION_STORE 0x2 |
@@ -21,11 +23,56 @@ struct perf_mem { | |||
21 | DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS); | 23 | DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS); |
22 | }; | 24 | }; |
23 | 25 | ||
26 | static int parse_record_events(const struct option *opt, | ||
27 | const char *str, int unset __maybe_unused) | ||
28 | { | ||
29 | struct perf_mem *mem = *(struct perf_mem **)opt->value; | ||
30 | int j; | ||
31 | |||
32 | if (strcmp(str, "list")) { | ||
33 | if (!perf_mem_events__parse(str)) { | ||
34 | mem->operation = 0; | ||
35 | return 0; | ||
36 | } | ||
37 | exit(-1); | ||
38 | } | ||
39 | |||
40 | for (j = 0; j < PERF_MEM_EVENTS__MAX; j++) { | ||
41 | struct perf_mem_event *e = &perf_mem_events[j]; | ||
42 | |||
43 | fprintf(stderr, "%-13s%-*s%s\n", | ||
44 | e->tag, | ||
45 | verbose ? 25 : 0, | ||
46 | verbose ? perf_mem_events__name(j) : "", | ||
47 | e->supported ? ": available" : ""); | ||
48 | } | ||
49 | exit(0); | ||
50 | } | ||
51 | |||
52 | static const char * const __usage[] = { | ||
53 | "perf mem record [<options>] [<command>]", | ||
54 | "perf mem record [<options>] -- <command> [<options>]", | ||
55 | NULL | ||
56 | }; | ||
57 | |||
58 | static const char * const *record_mem_usage = __usage; | ||
59 | |||
24 | static int __cmd_record(int argc, const char **argv, struct perf_mem *mem) | 60 | static int __cmd_record(int argc, const char **argv, struct perf_mem *mem) |
25 | { | 61 | { |
26 | int rec_argc, i = 0, j; | 62 | int rec_argc, i = 0, j; |
27 | const char **rec_argv; | 63 | const char **rec_argv; |
28 | int ret; | 64 | int ret; |
65 | struct option options[] = { | ||
66 | OPT_CALLBACK('e', "event", &mem, "event", | ||
67 | "event selector. use 'perf mem record -e list' to list available events", | ||
68 | parse_record_events), | ||
69 | OPT_INCR('v', "verbose", &verbose, | ||
70 | "be more verbose (show counter open errors, etc)"), | ||
71 | OPT_END() | ||
72 | }; | ||
73 | |||
74 | argc = parse_options(argc, argv, options, record_mem_usage, | ||
75 | PARSE_OPT_STOP_AT_NON_OPTION); | ||
29 | 76 | ||
30 | rec_argc = argc + 7; /* max number of arguments */ | 77 | rec_argc = argc + 7; /* max number of arguments */ |
31 | rec_argv = calloc(rec_argc + 1, sizeof(char *)); | 78 | rec_argv = calloc(rec_argc + 1, sizeof(char *)); |
@@ -35,23 +82,40 @@ static int __cmd_record(int argc, const char **argv, struct perf_mem *mem) | |||
35 | rec_argv[i++] = "record"; | 82 | rec_argv[i++] = "record"; |
36 | 83 | ||
37 | if (mem->operation & MEM_OPERATION_LOAD) | 84 | if (mem->operation & MEM_OPERATION_LOAD) |
85 | perf_mem_events[PERF_MEM_EVENTS__LOAD].record = true; | ||
86 | |||
87 | if (perf_mem_events[PERF_MEM_EVENTS__LOAD].record) | ||
38 | rec_argv[i++] = "-W"; | 88 | rec_argv[i++] = "-W"; |
39 | 89 | ||
40 | rec_argv[i++] = "-d"; | 90 | rec_argv[i++] = "-d"; |
41 | 91 | ||
42 | if (mem->operation & MEM_OPERATION_LOAD) { | 92 | for (j = 0; j < PERF_MEM_EVENTS__MAX; j++) { |
43 | rec_argv[i++] = "-e"; | 93 | if (!perf_mem_events[j].record) |
44 | rec_argv[i++] = "cpu/mem-loads/pp"; | 94 | continue; |
45 | } | 95 | |
96 | if (!perf_mem_events[j].supported) { | ||
97 | pr_err("failed: event '%s' not supported\n", | ||
98 | perf_mem_events__name(j)); | ||
99 | return -1; | ||
100 | } | ||
46 | 101 | ||
47 | if (mem->operation & MEM_OPERATION_STORE) { | ||
48 | rec_argv[i++] = "-e"; | 102 | rec_argv[i++] = "-e"; |
49 | rec_argv[i++] = "cpu/mem-stores/pp"; | 103 | rec_argv[i++] = perf_mem_events__name(j); |
50 | } | 104 | }; |
51 | 105 | ||
52 | for (j = 1; j < argc; j++, i++) | 106 | for (j = 0; j < argc; j++, i++) |
53 | rec_argv[i] = argv[j]; | 107 | rec_argv[i] = argv[j]; |
54 | 108 | ||
109 | if (verbose > 0) { | ||
110 | pr_debug("calling: record "); | ||
111 | |||
112 | while (rec_argv[j]) { | ||
113 | pr_debug("%s ", rec_argv[j]); | ||
114 | j++; | ||
115 | } | ||
116 | pr_debug("\n"); | ||
117 | } | ||
118 | |||
55 | ret = cmd_record(i, rec_argv, NULL); | 119 | ret = cmd_record(i, rec_argv, NULL); |
56 | free(rec_argv); | 120 | free(rec_argv); |
57 | return ret; | 121 | return ret; |
@@ -298,6 +362,10 @@ int cmd_mem(int argc, const char **argv, const char *prefix __maybe_unused) | |||
298 | NULL | 362 | NULL |
299 | }; | 363 | }; |
300 | 364 | ||
365 | if (perf_mem_events__init()) { | ||
366 | pr_err("failed: memory events not supported\n"); | ||
367 | return -1; | ||
368 | } | ||
301 | 369 | ||
302 | argc = parse_options_subcommand(argc, argv, mem_options, mem_subcommands, | 370 | argc = parse_options_subcommand(argc, argv, mem_options, mem_subcommands, |
303 | mem_usage, PARSE_OPT_STOP_AT_NON_OPTION); | 371 | mem_usage, PARSE_OPT_STOP_AT_NON_OPTION); |