#include #include #include "util.h" #include "debug.h" #include "builtin.h" #include #include "mem-events.h" static const char * const c2c_usage[] = { "perf c2c", NULL }; static int parse_record_events(const struct option *opt __maybe_unused, const char *str, int unset __maybe_unused) { bool *event_set = (bool *) opt->value; *event_set = true; return perf_mem_events__parse(str); } static const char * const __usage_record[] = { "perf c2c record [] []", "perf c2c record [] -- []", NULL }; static const char * const *record_mem_usage = __usage_record; static int perf_c2c__record(int argc, const char **argv) { int rec_argc, i = 0, j; const char **rec_argv; int ret; bool all_user = false, all_kernel = false; bool event_set = false; struct option options[] = { OPT_CALLBACK('e', "event", &event_set, "event", "event selector. Use 'perf mem record -e list' to list available events", parse_record_events), OPT_INCR('v', "verbose", &verbose, "be more verbose (show counter open errors, etc)"), OPT_BOOLEAN('u', "all-user", &all_user, "collect only user level data"), OPT_BOOLEAN('k', "all-kernel", &all_kernel, "collect only kernel level data"), OPT_UINTEGER('l', "ldlat", &perf_mem_events__loads_ldlat, "setup mem-loads latency"), OPT_END() }; if (perf_mem_events__init()) { pr_err("failed: memory events not supported\n"); return -1; } argc = parse_options(argc, argv, options, record_mem_usage, PARSE_OPT_KEEP_UNKNOWN); rec_argc = argc + 10; /* max number of arguments */ rec_argv = calloc(rec_argc + 1, sizeof(char *)); if (!rec_argv) return -1; rec_argv[i++] = "record"; if (!event_set) { perf_mem_events[PERF_MEM_EVENTS__LOAD].record = true; perf_mem_events[PERF_MEM_EVENTS__STORE].record = true; } if (perf_mem_events[PERF_MEM_EVENTS__LOAD].record) rec_argv[i++] = "-W"; rec_argv[i++] = "-d"; rec_argv[i++] = "--sample-cpu"; for (j = 0; j < PERF_MEM_EVENTS__MAX; j++) { if (!perf_mem_events[j].record) continue; if (!perf_mem_events[j].supported) { pr_err("failed: event '%s' not supported\n", perf_mem_events[j].name); return -1; } rec_argv[i++] = "-e"; rec_argv[i++] = perf_mem_events__name(j); }; if (all_user) rec_argv[i++] = "--all-user"; if (all_kernel) rec_argv[i++] = "--all-kernel"; for (j = 0; j < argc; j++, i++) rec_argv[i] = argv[j]; if (verbose > 0) { pr_debug("calling: "); j = 0; while (rec_argv[j]) { pr_debug("%s ", rec_argv[j]); j++; } pr_debug("\n"); } ret = cmd_record(i, rec_argv, NULL); free(rec_argv); return ret; } int cmd_c2c(int argc, const char **argv, const char *prefix __maybe_unused) { const struct option c2c_options[] = { OPT_INCR('v', "verbose", &verbose, "be more verbose"), OPT_END() }; argc = parse_options(argc, argv, c2c_options, c2c_usage, PARSE_OPT_STOP_AT_NON_OPTION); if (!argc) usage_with_options(c2c_usage, c2c_options); if (!strncmp(argv[0], "rec", 3)) { return perf_c2c__record(argc, argv); } else { usage_with_options(c2c_usage, c2c_options); } return 0; }