blob: 3fac3a294bddb845426ea6c840719c23a896416d [file] [log] [blame]
Jiri Olsa7aef3bf2016-09-22 17:36:38 +02001#include <linux/compiler.h>
2#include <linux/kernel.h>
3#include "util.h"
4#include "debug.h"
5#include "builtin.h"
6#include <subcmd/parse-options.h>
Jiri Olsa39bcd4a2016-09-22 17:36:39 +02007#include "mem-events.h"
Jiri Olsa903a6f12016-09-22 17:36:40 +02008#include "session.h"
9#include "hist.h"
10#include "tool.h"
11#include "data.h"
12
13struct perf_c2c {
14 struct perf_tool tool;
15};
16
17static struct perf_c2c c2c;
Jiri Olsa7aef3bf2016-09-22 17:36:38 +020018
19static const char * const c2c_usage[] = {
Jiri Olsa903a6f12016-09-22 17:36:40 +020020 "perf c2c {record|report}",
Jiri Olsa7aef3bf2016-09-22 17:36:38 +020021 NULL
22};
23
Jiri Olsa903a6f12016-09-22 17:36:40 +020024static const char * const __usage_report[] = {
25 "perf c2c report",
26 NULL
27};
28
29static const char * const *report_c2c_usage = __usage_report;
30
31static int perf_c2c__report(int argc, const char **argv)
32{
33 struct perf_session *session;
34 struct perf_data_file file = {
35 .mode = PERF_DATA_MODE_READ,
36 };
37 const struct option c2c_options[] = {
38 OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name,
39 "file", "vmlinux pathname"),
40 OPT_INCR('v', "verbose", &verbose,
41 "be more verbose (show counter open errors, etc)"),
42 OPT_STRING('i', "input", &input_name, "file",
43 "the input file to process"),
44 OPT_END()
45 };
46 int err = 0;
47
48 argc = parse_options(argc, argv, c2c_options, report_c2c_usage,
49 PARSE_OPT_STOP_AT_NON_OPTION);
50 if (!argc)
51 usage_with_options(report_c2c_usage, c2c_options);
52
53 file.path = input_name;
54
55 session = perf_session__new(&file, 0, &c2c.tool);
56 if (session == NULL) {
57 pr_debug("No memory for session\n");
58 goto out;
59 }
60
61 if (symbol__init(&session->header.env) < 0)
62 goto out_session;
63
64 /* No pipe support at the moment. */
65 if (perf_data_file__is_pipe(session->file)) {
66 pr_debug("No pipe support at the moment.\n");
67 goto out_session;
68 }
69
70out_session:
71 perf_session__delete(session);
72out:
73 return err;
74}
75
Jiri Olsa39bcd4a2016-09-22 17:36:39 +020076static int parse_record_events(const struct option *opt __maybe_unused,
77 const char *str, int unset __maybe_unused)
78{
79 bool *event_set = (bool *) opt->value;
80
81 *event_set = true;
82 return perf_mem_events__parse(str);
83}
84
85
86static const char * const __usage_record[] = {
87 "perf c2c record [<options>] [<command>]",
88 "perf c2c record [<options>] -- <command> [<options>]",
89 NULL
90};
91
92static const char * const *record_mem_usage = __usage_record;
93
94static int perf_c2c__record(int argc, const char **argv)
95{
96 int rec_argc, i = 0, j;
97 const char **rec_argv;
98 int ret;
99 bool all_user = false, all_kernel = false;
100 bool event_set = false;
101 struct option options[] = {
102 OPT_CALLBACK('e', "event", &event_set, "event",
103 "event selector. Use 'perf mem record -e list' to list available events",
104 parse_record_events),
105 OPT_INCR('v', "verbose", &verbose,
106 "be more verbose (show counter open errors, etc)"),
107 OPT_BOOLEAN('u', "all-user", &all_user, "collect only user level data"),
108 OPT_BOOLEAN('k', "all-kernel", &all_kernel, "collect only kernel level data"),
109 OPT_UINTEGER('l', "ldlat", &perf_mem_events__loads_ldlat, "setup mem-loads latency"),
110 OPT_END()
111 };
112
113 if (perf_mem_events__init()) {
114 pr_err("failed: memory events not supported\n");
115 return -1;
116 }
117
118 argc = parse_options(argc, argv, options, record_mem_usage,
119 PARSE_OPT_KEEP_UNKNOWN);
120
121 rec_argc = argc + 10; /* max number of arguments */
122 rec_argv = calloc(rec_argc + 1, sizeof(char *));
123 if (!rec_argv)
124 return -1;
125
126 rec_argv[i++] = "record";
127
128 if (!event_set) {
129 perf_mem_events[PERF_MEM_EVENTS__LOAD].record = true;
130 perf_mem_events[PERF_MEM_EVENTS__STORE].record = true;
131 }
132
133 if (perf_mem_events[PERF_MEM_EVENTS__LOAD].record)
134 rec_argv[i++] = "-W";
135
136 rec_argv[i++] = "-d";
137 rec_argv[i++] = "--sample-cpu";
138
139 for (j = 0; j < PERF_MEM_EVENTS__MAX; j++) {
140 if (!perf_mem_events[j].record)
141 continue;
142
143 if (!perf_mem_events[j].supported) {
144 pr_err("failed: event '%s' not supported\n",
145 perf_mem_events[j].name);
146 return -1;
147 }
148
149 rec_argv[i++] = "-e";
150 rec_argv[i++] = perf_mem_events__name(j);
151 };
152
153 if (all_user)
154 rec_argv[i++] = "--all-user";
155
156 if (all_kernel)
157 rec_argv[i++] = "--all-kernel";
158
159 for (j = 0; j < argc; j++, i++)
160 rec_argv[i] = argv[j];
161
162 if (verbose > 0) {
163 pr_debug("calling: ");
164
165 j = 0;
166
167 while (rec_argv[j]) {
168 pr_debug("%s ", rec_argv[j]);
169 j++;
170 }
171 pr_debug("\n");
172 }
173
174 ret = cmd_record(i, rec_argv, NULL);
175 free(rec_argv);
176 return ret;
177}
178
Jiri Olsa7aef3bf2016-09-22 17:36:38 +0200179int cmd_c2c(int argc, const char **argv, const char *prefix __maybe_unused)
180{
181 const struct option c2c_options[] = {
182 OPT_INCR('v', "verbose", &verbose, "be more verbose"),
183 OPT_END()
184 };
185
186 argc = parse_options(argc, argv, c2c_options, c2c_usage,
187 PARSE_OPT_STOP_AT_NON_OPTION);
Jiri Olsa39bcd4a2016-09-22 17:36:39 +0200188
189 if (!argc)
190 usage_with_options(c2c_usage, c2c_options);
191
192 if (!strncmp(argv[0], "rec", 3)) {
193 return perf_c2c__record(argc, argv);
Jiri Olsa903a6f12016-09-22 17:36:40 +0200194 } else if (!strncmp(argv[0], "rep", 3)) {
195 return perf_c2c__report(argc, argv);
Jiri Olsa39bcd4a2016-09-22 17:36:39 +0200196 } else {
197 usage_with_options(c2c_usage, c2c_options);
198 }
199
Jiri Olsa7aef3bf2016-09-22 17:36:38 +0200200 return 0;
201}