0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043 #include "builtin.h"
0044 #include "perf.h"
0045 #include "util/cgroup.h"
0046 #include <subcmd/parse-options.h>
0047 #include "util/parse-events.h"
0048 #include "util/pmu.h"
0049 #include "util/event.h"
0050 #include "util/evlist.h"
0051 #include "util/evlist-hybrid.h"
0052 #include "util/evsel.h"
0053 #include "util/debug.h"
0054 #include "util/color.h"
0055 #include "util/stat.h"
0056 #include "util/header.h"
0057 #include "util/cpumap.h"
0058 #include "util/thread_map.h"
0059 #include "util/counts.h"
0060 #include "util/topdown.h"
0061 #include "util/session.h"
0062 #include "util/tool.h"
0063 #include "util/string2.h"
0064 #include "util/metricgroup.h"
0065 #include "util/synthetic-events.h"
0066 #include "util/target.h"
0067 #include "util/time-utils.h"
0068 #include "util/top.h"
0069 #include "util/affinity.h"
0070 #include "util/pfm.h"
0071 #include "util/bpf_counter.h"
0072 #include "util/iostat.h"
0073 #include "util/pmu-hybrid.h"
0074 #include "asm/bug.h"
0075
0076 #include <linux/time64.h>
0077 #include <linux/zalloc.h>
0078 #include <api/fs/fs.h>
0079 #include <errno.h>
0080 #include <signal.h>
0081 #include <stdlib.h>
0082 #include <sys/prctl.h>
0083 #include <inttypes.h>
0084 #include <locale.h>
0085 #include <math.h>
0086 #include <sys/types.h>
0087 #include <sys/stat.h>
0088 #include <sys/wait.h>
0089 #include <unistd.h>
0090 #include <sys/time.h>
0091 #include <sys/resource.h>
0092 #include <linux/err.h>
0093
0094 #include <linux/ctype.h>
0095 #include <perf/evlist.h>
0096
0097 #define DEFAULT_SEPARATOR " "
0098 #define FREEZE_ON_SMI_PATH "devices/cpu/freeze_on_smi"
0099
0100 static void print_counters(struct timespec *ts, int argc, const char **argv);
0101
0102
0103 static const char *transaction_attrs = {
0104 "task-clock,"
0105 "{"
0106 "instructions,"
0107 "cycles,"
0108 "cpu/cycles-t/,"
0109 "cpu/tx-start/,"
0110 "cpu/el-start/,"
0111 "cpu/cycles-ct/"
0112 "}"
0113 };
0114
0115
0116 static const char * transaction_limited_attrs = {
0117 "task-clock,"
0118 "{"
0119 "instructions,"
0120 "cycles,"
0121 "cpu/cycles-t/,"
0122 "cpu/tx-start/"
0123 "}"
0124 };
0125
0126 static const char * topdown_attrs[] = {
0127 "topdown-total-slots",
0128 "topdown-slots-retired",
0129 "topdown-recovery-bubbles",
0130 "topdown-fetch-bubbles",
0131 "topdown-slots-issued",
0132 NULL,
0133 };
0134
0135 static const char *topdown_metric_attrs[] = {
0136 "slots",
0137 "topdown-retiring",
0138 "topdown-bad-spec",
0139 "topdown-fe-bound",
0140 "topdown-be-bound",
0141 NULL,
0142 };
0143
0144 static const char *topdown_metric_L2_attrs[] = {
0145 "slots",
0146 "topdown-retiring",
0147 "topdown-bad-spec",
0148 "topdown-fe-bound",
0149 "topdown-be-bound",
0150 "topdown-heavy-ops",
0151 "topdown-br-mispredict",
0152 "topdown-fetch-lat",
0153 "topdown-mem-bound",
0154 NULL,
0155 };
0156
0157 #define TOPDOWN_MAX_LEVEL 2
0158
0159 static const char *smi_cost_attrs = {
0160 "{"
0161 "msr/aperf/,"
0162 "msr/smi/,"
0163 "cycles"
0164 "}"
0165 };
0166
0167 static struct evlist *evsel_list;
0168 static bool all_counters_use_bpf = true;
0169
0170 static struct target target = {
0171 .uid = UINT_MAX,
0172 };
0173
0174 #define METRIC_ONLY_LEN 20
0175
0176 static volatile pid_t child_pid = -1;
0177 static int detailed_run = 0;
0178 static bool transaction_run;
0179 static bool topdown_run = false;
0180 static bool smi_cost = false;
0181 static bool smi_reset = false;
0182 static int big_num_opt = -1;
0183 static bool group = false;
0184 static const char *pre_cmd = NULL;
0185 static const char *post_cmd = NULL;
0186 static bool sync_run = false;
0187 static bool forever = false;
0188 static bool force_metric_only = false;
0189 static struct timespec ref_time;
0190 static bool append_file;
0191 static bool interval_count;
0192 static const char *output_name;
0193 static int output_fd;
0194
0195 struct perf_stat {
0196 bool record;
0197 struct perf_data data;
0198 struct perf_session *session;
0199 u64 bytes_written;
0200 struct perf_tool tool;
0201 bool maps_allocated;
0202 struct perf_cpu_map *cpus;
0203 struct perf_thread_map *threads;
0204 enum aggr_mode aggr_mode;
0205 };
0206
0207 static struct perf_stat perf_stat;
0208 #define STAT_RECORD perf_stat.record
0209
0210 static volatile int done = 0;
0211
0212 static struct perf_stat_config stat_config = {
0213 .aggr_mode = AGGR_GLOBAL,
0214 .scale = true,
0215 .unit_width = 4,
0216 .run_count = 1,
0217 .metric_only_len = METRIC_ONLY_LEN,
0218 .walltime_nsecs_stats = &walltime_nsecs_stats,
0219 .ru_stats = &ru_stats,
0220 .big_num = true,
0221 .ctl_fd = -1,
0222 .ctl_fd_ack = -1,
0223 .iostat_run = false,
0224 };
0225
0226 static bool cpus_map_matched(struct evsel *a, struct evsel *b)
0227 {
0228 if (!a->core.cpus && !b->core.cpus)
0229 return true;
0230
0231 if (!a->core.cpus || !b->core.cpus)
0232 return false;
0233
0234 if (perf_cpu_map__nr(a->core.cpus) != perf_cpu_map__nr(b->core.cpus))
0235 return false;
0236
0237 for (int i = 0; i < perf_cpu_map__nr(a->core.cpus); i++) {
0238 if (perf_cpu_map__cpu(a->core.cpus, i).cpu !=
0239 perf_cpu_map__cpu(b->core.cpus, i).cpu)
0240 return false;
0241 }
0242
0243 return true;
0244 }
0245
0246 static void evlist__check_cpu_maps(struct evlist *evlist)
0247 {
0248 struct evsel *evsel, *pos, *leader;
0249 char buf[1024];
0250
0251 if (evlist__has_hybrid(evlist))
0252 evlist__warn_hybrid_group(evlist);
0253
0254 evlist__for_each_entry(evlist, evsel) {
0255 leader = evsel__leader(evsel);
0256
0257
0258 if (leader == evsel)
0259 continue;
0260 if (cpus_map_matched(leader, evsel))
0261 continue;
0262
0263
0264 WARN_ONCE(1, "WARNING: grouped events cpus do not match, disabling group:\n");
0265 evsel__group_desc(leader, buf, sizeof(buf));
0266 pr_warning(" %s\n", buf);
0267
0268 if (verbose) {
0269 cpu_map__snprint(leader->core.cpus, buf, sizeof(buf));
0270 pr_warning(" %s: %s\n", leader->name, buf);
0271 cpu_map__snprint(evsel->core.cpus, buf, sizeof(buf));
0272 pr_warning(" %s: %s\n", evsel->name, buf);
0273 }
0274
0275 for_each_group_evsel(pos, leader)
0276 evsel__remove_from_group(pos, leader);
0277 }
0278 }
0279
0280 static inline void diff_timespec(struct timespec *r, struct timespec *a,
0281 struct timespec *b)
0282 {
0283 r->tv_sec = a->tv_sec - b->tv_sec;
0284 if (a->tv_nsec < b->tv_nsec) {
0285 r->tv_nsec = a->tv_nsec + NSEC_PER_SEC - b->tv_nsec;
0286 r->tv_sec--;
0287 } else {
0288 r->tv_nsec = a->tv_nsec - b->tv_nsec ;
0289 }
0290 }
0291
0292 static void perf_stat__reset_stats(void)
0293 {
0294 int i;
0295
0296 evlist__reset_stats(evsel_list);
0297 perf_stat__reset_shadow_stats();
0298
0299 for (i = 0; i < stat_config.stats_num; i++)
0300 perf_stat__reset_shadow_per_stat(&stat_config.stats[i]);
0301 }
0302
0303 static int process_synthesized_event(struct perf_tool *tool __maybe_unused,
0304 union perf_event *event,
0305 struct perf_sample *sample __maybe_unused,
0306 struct machine *machine __maybe_unused)
0307 {
0308 if (perf_data__write(&perf_stat.data, event, event->header.size) < 0) {
0309 pr_err("failed to write perf data, error: %m\n");
0310 return -1;
0311 }
0312
0313 perf_stat.bytes_written += event->header.size;
0314 return 0;
0315 }
0316
0317 static int write_stat_round_event(u64 tm, u64 type)
0318 {
0319 return perf_event__synthesize_stat_round(NULL, tm, type,
0320 process_synthesized_event,
0321 NULL);
0322 }
0323
0324 #define WRITE_STAT_ROUND_EVENT(time, interval) \
0325 write_stat_round_event(time, PERF_STAT_ROUND_TYPE__ ## interval)
0326
0327 #define SID(e, x, y) xyarray__entry(e->core.sample_id, x, y)
0328
0329 static int evsel__write_stat_event(struct evsel *counter, int cpu_map_idx, u32 thread,
0330 struct perf_counts_values *count)
0331 {
0332 struct perf_sample_id *sid = SID(counter, cpu_map_idx, thread);
0333 struct perf_cpu cpu = perf_cpu_map__cpu(evsel__cpus(counter), cpu_map_idx);
0334
0335 return perf_event__synthesize_stat(NULL, cpu, thread, sid->id, count,
0336 process_synthesized_event, NULL);
0337 }
0338
0339 static int read_single_counter(struct evsel *counter, int cpu_map_idx,
0340 int thread, struct timespec *rs)
0341 {
0342 switch(counter->tool_event) {
0343 case PERF_TOOL_DURATION_TIME: {
0344 u64 val = rs->tv_nsec + rs->tv_sec*1000000000ULL;
0345 struct perf_counts_values *count =
0346 perf_counts(counter->counts, cpu_map_idx, thread);
0347 count->ena = count->run = val;
0348 count->val = val;
0349 return 0;
0350 }
0351 case PERF_TOOL_USER_TIME:
0352 case PERF_TOOL_SYSTEM_TIME: {
0353 u64 val;
0354 struct perf_counts_values *count =
0355 perf_counts(counter->counts, cpu_map_idx, thread);
0356 if (counter->tool_event == PERF_TOOL_USER_TIME)
0357 val = ru_stats.ru_utime_usec_stat.mean;
0358 else
0359 val = ru_stats.ru_stime_usec_stat.mean;
0360 count->ena = count->run = val;
0361 count->val = val;
0362 return 0;
0363 }
0364 default:
0365 case PERF_TOOL_NONE:
0366 return evsel__read_counter(counter, cpu_map_idx, thread);
0367 case PERF_TOOL_MAX:
0368
0369 return 0;
0370 }
0371 }
0372
0373
0374
0375
0376
0377 static int read_counter_cpu(struct evsel *counter, struct timespec *rs, int cpu_map_idx)
0378 {
0379 int nthreads = perf_thread_map__nr(evsel_list->core.threads);
0380 int thread;
0381
0382 if (!counter->supported)
0383 return -ENOENT;
0384
0385 for (thread = 0; thread < nthreads; thread++) {
0386 struct perf_counts_values *count;
0387
0388 count = perf_counts(counter->counts, cpu_map_idx, thread);
0389
0390
0391
0392
0393
0394 if (!perf_counts__is_loaded(counter->counts, cpu_map_idx, thread) &&
0395 read_single_counter(counter, cpu_map_idx, thread, rs)) {
0396 counter->counts->scaled = -1;
0397 perf_counts(counter->counts, cpu_map_idx, thread)->ena = 0;
0398 perf_counts(counter->counts, cpu_map_idx, thread)->run = 0;
0399 return -1;
0400 }
0401
0402 perf_counts__set_loaded(counter->counts, cpu_map_idx, thread, false);
0403
0404 if (STAT_RECORD) {
0405 if (evsel__write_stat_event(counter, cpu_map_idx, thread, count)) {
0406 pr_err("failed to write stat event\n");
0407 return -1;
0408 }
0409 }
0410
0411 if (verbose > 1) {
0412 fprintf(stat_config.output,
0413 "%s: %d: %" PRIu64 " %" PRIu64 " %" PRIu64 "\n",
0414 evsel__name(counter),
0415 perf_cpu_map__cpu(evsel__cpus(counter),
0416 cpu_map_idx).cpu,
0417 count->val, count->ena, count->run);
0418 }
0419 }
0420
0421 return 0;
0422 }
0423
0424 static int read_affinity_counters(struct timespec *rs)
0425 {
0426 struct evlist_cpu_iterator evlist_cpu_itr;
0427 struct affinity saved_affinity, *affinity;
0428
0429 if (all_counters_use_bpf)
0430 return 0;
0431
0432 if (!target__has_cpu(&target) || target__has_per_thread(&target))
0433 affinity = NULL;
0434 else if (affinity__setup(&saved_affinity) < 0)
0435 return -1;
0436 else
0437 affinity = &saved_affinity;
0438
0439 evlist__for_each_cpu(evlist_cpu_itr, evsel_list, affinity) {
0440 struct evsel *counter = evlist_cpu_itr.evsel;
0441
0442 if (evsel__is_bpf(counter))
0443 continue;
0444
0445 if (!counter->err) {
0446 counter->err = read_counter_cpu(counter, rs,
0447 evlist_cpu_itr.cpu_map_idx);
0448 }
0449 }
0450 if (affinity)
0451 affinity__cleanup(&saved_affinity);
0452
0453 return 0;
0454 }
0455
0456 static int read_bpf_map_counters(void)
0457 {
0458 struct evsel *counter;
0459 int err;
0460
0461 evlist__for_each_entry(evsel_list, counter) {
0462 if (!evsel__is_bpf(counter))
0463 continue;
0464
0465 err = bpf_counter__read(counter);
0466 if (err)
0467 return err;
0468 }
0469 return 0;
0470 }
0471
0472 static void read_counters(struct timespec *rs)
0473 {
0474 struct evsel *counter;
0475
0476 if (!stat_config.stop_read_counter) {
0477 if (read_bpf_map_counters() ||
0478 read_affinity_counters(rs))
0479 return;
0480 }
0481
0482 evlist__for_each_entry(evsel_list, counter) {
0483 if (counter->err)
0484 pr_debug("failed to read counter %s\n", counter->name);
0485 if (counter->err == 0 && perf_stat_process_counter(&stat_config, counter))
0486 pr_warning("failed to process counter %s\n", counter->name);
0487 counter->err = 0;
0488 }
0489 }
0490
0491 static int runtime_stat_new(struct perf_stat_config *config, int nthreads)
0492 {
0493 int i;
0494
0495 config->stats = calloc(nthreads, sizeof(struct runtime_stat));
0496 if (!config->stats)
0497 return -1;
0498
0499 config->stats_num = nthreads;
0500
0501 for (i = 0; i < nthreads; i++)
0502 runtime_stat__init(&config->stats[i]);
0503
0504 return 0;
0505 }
0506
0507 static void runtime_stat_delete(struct perf_stat_config *config)
0508 {
0509 int i;
0510
0511 if (!config->stats)
0512 return;
0513
0514 for (i = 0; i < config->stats_num; i++)
0515 runtime_stat__exit(&config->stats[i]);
0516
0517 zfree(&config->stats);
0518 }
0519
0520 static void runtime_stat_reset(struct perf_stat_config *config)
0521 {
0522 int i;
0523
0524 if (!config->stats)
0525 return;
0526
0527 for (i = 0; i < config->stats_num; i++)
0528 perf_stat__reset_shadow_per_stat(&config->stats[i]);
0529 }
0530
0531 static void process_interval(void)
0532 {
0533 struct timespec ts, rs;
0534
0535 clock_gettime(CLOCK_MONOTONIC, &ts);
0536 diff_timespec(&rs, &ts, &ref_time);
0537
0538 perf_stat__reset_shadow_per_stat(&rt_stat);
0539 runtime_stat_reset(&stat_config);
0540 read_counters(&rs);
0541
0542 if (STAT_RECORD) {
0543 if (WRITE_STAT_ROUND_EVENT(rs.tv_sec * NSEC_PER_SEC + rs.tv_nsec, INTERVAL))
0544 pr_err("failed to write stat round event\n");
0545 }
0546
0547 init_stats(&walltime_nsecs_stats);
0548 update_stats(&walltime_nsecs_stats, stat_config.interval * 1000000ULL);
0549 print_counters(&rs, 0, NULL);
0550 }
0551
0552 static bool handle_interval(unsigned int interval, int *times)
0553 {
0554 if (interval) {
0555 process_interval();
0556 if (interval_count && !(--(*times)))
0557 return true;
0558 }
0559 return false;
0560 }
0561
0562 static int enable_counters(void)
0563 {
0564 struct evsel *evsel;
0565 int err;
0566
0567 evlist__for_each_entry(evsel_list, evsel) {
0568 if (!evsel__is_bpf(evsel))
0569 continue;
0570
0571 err = bpf_counter__enable(evsel);
0572 if (err)
0573 return err;
0574 }
0575
0576 if (stat_config.initial_delay < 0) {
0577 pr_info(EVLIST_DISABLED_MSG);
0578 return 0;
0579 }
0580
0581 if (stat_config.initial_delay > 0) {
0582 pr_info(EVLIST_DISABLED_MSG);
0583 usleep(stat_config.initial_delay * USEC_PER_MSEC);
0584 }
0585
0586
0587
0588
0589
0590
0591 if (!target__none(&target) || stat_config.initial_delay) {
0592 if (!all_counters_use_bpf)
0593 evlist__enable(evsel_list);
0594 if (stat_config.initial_delay > 0)
0595 pr_info(EVLIST_ENABLED_MSG);
0596 }
0597 return 0;
0598 }
0599
0600 static void disable_counters(void)
0601 {
0602 struct evsel *counter;
0603
0604
0605
0606
0607
0608
0609 if (!target__none(&target)) {
0610 evlist__for_each_entry(evsel_list, counter)
0611 bpf_counter__disable(counter);
0612 if (!all_counters_use_bpf)
0613 evlist__disable(evsel_list);
0614 }
0615 }
0616
0617 static volatile int workload_exec_errno;
0618
0619
0620
0621
0622
0623
0624 static void workload_exec_failed_signal(int signo __maybe_unused, siginfo_t *info,
0625 void *ucontext __maybe_unused)
0626 {
0627 workload_exec_errno = info->si_value.sival_int;
0628 }
0629
0630 static bool evsel__should_store_id(struct evsel *counter)
0631 {
0632 return STAT_RECORD || counter->core.attr.read_format & PERF_FORMAT_ID;
0633 }
0634
0635 static bool is_target_alive(struct target *_target,
0636 struct perf_thread_map *threads)
0637 {
0638 struct stat st;
0639 int i;
0640
0641 if (!target__has_task(_target))
0642 return true;
0643
0644 for (i = 0; i < threads->nr; i++) {
0645 char path[PATH_MAX];
0646
0647 scnprintf(path, PATH_MAX, "%s/%d", procfs__mountpoint(),
0648 threads->map[i].pid);
0649
0650 if (!stat(path, &st))
0651 return true;
0652 }
0653
0654 return false;
0655 }
0656
0657 static void process_evlist(struct evlist *evlist, unsigned int interval)
0658 {
0659 enum evlist_ctl_cmd cmd = EVLIST_CTL_CMD_UNSUPPORTED;
0660
0661 if (evlist__ctlfd_process(evlist, &cmd) > 0) {
0662 switch (cmd) {
0663 case EVLIST_CTL_CMD_ENABLE:
0664 if (interval)
0665 process_interval();
0666 break;
0667 case EVLIST_CTL_CMD_DISABLE:
0668 if (interval)
0669 process_interval();
0670 break;
0671 case EVLIST_CTL_CMD_SNAPSHOT:
0672 case EVLIST_CTL_CMD_ACK:
0673 case EVLIST_CTL_CMD_UNSUPPORTED:
0674 case EVLIST_CTL_CMD_EVLIST:
0675 case EVLIST_CTL_CMD_STOP:
0676 case EVLIST_CTL_CMD_PING:
0677 default:
0678 break;
0679 }
0680 }
0681 }
0682
0683 static void compute_tts(struct timespec *time_start, struct timespec *time_stop,
0684 int *time_to_sleep)
0685 {
0686 int tts = *time_to_sleep;
0687 struct timespec time_diff;
0688
0689 diff_timespec(&time_diff, time_stop, time_start);
0690
0691 tts -= time_diff.tv_sec * MSEC_PER_SEC +
0692 time_diff.tv_nsec / NSEC_PER_MSEC;
0693
0694 if (tts < 0)
0695 tts = 0;
0696
0697 *time_to_sleep = tts;
0698 }
0699
0700 static int dispatch_events(bool forks, int timeout, int interval, int *times)
0701 {
0702 int child_exited = 0, status = 0;
0703 int time_to_sleep, sleep_time;
0704 struct timespec time_start, time_stop;
0705
0706 if (interval)
0707 sleep_time = interval;
0708 else if (timeout)
0709 sleep_time = timeout;
0710 else
0711 sleep_time = 1000;
0712
0713 time_to_sleep = sleep_time;
0714
0715 while (!done) {
0716 if (forks)
0717 child_exited = waitpid(child_pid, &status, WNOHANG);
0718 else
0719 child_exited = !is_target_alive(&target, evsel_list->core.threads) ? 1 : 0;
0720
0721 if (child_exited)
0722 break;
0723
0724 clock_gettime(CLOCK_MONOTONIC, &time_start);
0725 if (!(evlist__poll(evsel_list, time_to_sleep) > 0)) {
0726 if (timeout || handle_interval(interval, times))
0727 break;
0728 time_to_sleep = sleep_time;
0729 } else {
0730 process_evlist(evsel_list, interval);
0731 clock_gettime(CLOCK_MONOTONIC, &time_stop);
0732 compute_tts(&time_start, &time_stop, &time_to_sleep);
0733 }
0734 }
0735
0736 return status;
0737 }
0738
0739 enum counter_recovery {
0740 COUNTER_SKIP,
0741 COUNTER_RETRY,
0742 COUNTER_FATAL,
0743 };
0744
0745 static enum counter_recovery stat_handle_error(struct evsel *counter)
0746 {
0747 char msg[BUFSIZ];
0748
0749
0750
0751
0752 if (errno == EINVAL || errno == ENOSYS ||
0753 errno == ENOENT || errno == EOPNOTSUPP ||
0754 errno == ENXIO) {
0755 if (verbose > 0)
0756 ui__warning("%s event is not supported by the kernel.\n",
0757 evsel__name(counter));
0758 counter->supported = false;
0759
0760
0761
0762
0763 counter->errored = true;
0764
0765 if ((evsel__leader(counter) != counter) ||
0766 !(counter->core.leader->nr_members > 1))
0767 return COUNTER_SKIP;
0768 } else if (evsel__fallback(counter, errno, msg, sizeof(msg))) {
0769 if (verbose > 0)
0770 ui__warning("%s\n", msg);
0771 return COUNTER_RETRY;
0772 } else if (target__has_per_thread(&target) &&
0773 evsel_list->core.threads &&
0774 evsel_list->core.threads->err_thread != -1) {
0775
0776
0777
0778
0779 if (!thread_map__remove(evsel_list->core.threads,
0780 evsel_list->core.threads->err_thread)) {
0781 evsel_list->core.threads->err_thread = -1;
0782 return COUNTER_RETRY;
0783 }
0784 }
0785
0786 evsel__open_strerror(counter, &target, errno, msg, sizeof(msg));
0787 ui__error("%s\n", msg);
0788
0789 if (child_pid != -1)
0790 kill(child_pid, SIGTERM);
0791 return COUNTER_FATAL;
0792 }
0793
0794 static int __run_perf_stat(int argc, const char **argv, int run_idx)
0795 {
0796 int interval = stat_config.interval;
0797 int times = stat_config.times;
0798 int timeout = stat_config.timeout;
0799 char msg[BUFSIZ];
0800 unsigned long long t0, t1;
0801 struct evsel *counter;
0802 size_t l;
0803 int status = 0;
0804 const bool forks = (argc > 0);
0805 bool is_pipe = STAT_RECORD ? perf_stat.data.is_pipe : false;
0806 struct evlist_cpu_iterator evlist_cpu_itr;
0807 struct affinity saved_affinity, *affinity = NULL;
0808 int err;
0809 bool second_pass = false;
0810
0811 if (forks) {
0812 if (evlist__prepare_workload(evsel_list, &target, argv, is_pipe, workload_exec_failed_signal) < 0) {
0813 perror("failed to prepare workload");
0814 return -1;
0815 }
0816 child_pid = evsel_list->workload.pid;
0817 }
0818
0819 if (group)
0820 evlist__set_leader(evsel_list);
0821
0822 if (!cpu_map__is_dummy(evsel_list->core.user_requested_cpus)) {
0823 if (affinity__setup(&saved_affinity) < 0)
0824 return -1;
0825 affinity = &saved_affinity;
0826 }
0827
0828 evlist__for_each_entry(evsel_list, counter) {
0829 counter->reset_group = false;
0830 if (bpf_counter__load(counter, &target))
0831 return -1;
0832 if (!evsel__is_bpf(counter))
0833 all_counters_use_bpf = false;
0834 }
0835
0836 evlist__for_each_cpu(evlist_cpu_itr, evsel_list, affinity) {
0837 counter = evlist_cpu_itr.evsel;
0838
0839
0840
0841
0842
0843 if (target.use_bpf)
0844 break;
0845
0846 if (counter->reset_group || counter->errored)
0847 continue;
0848 if (evsel__is_bpf(counter))
0849 continue;
0850 try_again:
0851 if (create_perf_stat_counter(counter, &stat_config, &target,
0852 evlist_cpu_itr.cpu_map_idx) < 0) {
0853
0854
0855
0856
0857
0858
0859
0860
0861 if ((errno == EINVAL || errno == EBADF) &&
0862 evsel__leader(counter) != counter &&
0863 counter->weak_group) {
0864 evlist__reset_weak_group(evsel_list, counter, false);
0865 assert(counter->reset_group);
0866 second_pass = true;
0867 continue;
0868 }
0869
0870 switch (stat_handle_error(counter)) {
0871 case COUNTER_FATAL:
0872 return -1;
0873 case COUNTER_RETRY:
0874 goto try_again;
0875 case COUNTER_SKIP:
0876 continue;
0877 default:
0878 break;
0879 }
0880
0881 }
0882 counter->supported = true;
0883 }
0884
0885 if (second_pass) {
0886
0887
0888
0889
0890
0891
0892 evlist__for_each_cpu(evlist_cpu_itr, evsel_list, affinity) {
0893 counter = evlist_cpu_itr.evsel;
0894
0895 if (!counter->reset_group && !counter->errored)
0896 continue;
0897
0898 perf_evsel__close_cpu(&counter->core, evlist_cpu_itr.cpu_map_idx);
0899 }
0900
0901 evlist__for_each_cpu(evlist_cpu_itr, evsel_list, affinity) {
0902 counter = evlist_cpu_itr.evsel;
0903
0904 if (!counter->reset_group && !counter->errored)
0905 continue;
0906 if (!counter->reset_group)
0907 continue;
0908 try_again_reset:
0909 pr_debug2("reopening weak %s\n", evsel__name(counter));
0910 if (create_perf_stat_counter(counter, &stat_config, &target,
0911 evlist_cpu_itr.cpu_map_idx) < 0) {
0912
0913 switch (stat_handle_error(counter)) {
0914 case COUNTER_FATAL:
0915 return -1;
0916 case COUNTER_RETRY:
0917 goto try_again_reset;
0918 case COUNTER_SKIP:
0919 continue;
0920 default:
0921 break;
0922 }
0923 }
0924 counter->supported = true;
0925 }
0926 }
0927 affinity__cleanup(affinity);
0928
0929 evlist__for_each_entry(evsel_list, counter) {
0930 if (!counter->supported) {
0931 perf_evsel__free_fd(&counter->core);
0932 continue;
0933 }
0934
0935 l = strlen(counter->unit);
0936 if (l > stat_config.unit_width)
0937 stat_config.unit_width = l;
0938
0939 if (evsel__should_store_id(counter) &&
0940 evsel__store_ids(counter, evsel_list))
0941 return -1;
0942 }
0943
0944 if (evlist__apply_filters(evsel_list, &counter)) {
0945 pr_err("failed to set filter \"%s\" on event %s with %d (%s)\n",
0946 counter->filter, evsel__name(counter), errno,
0947 str_error_r(errno, msg, sizeof(msg)));
0948 return -1;
0949 }
0950
0951 if (STAT_RECORD) {
0952 int fd = perf_data__fd(&perf_stat.data);
0953
0954 if (is_pipe) {
0955 err = perf_header__write_pipe(perf_data__fd(&perf_stat.data));
0956 } else {
0957 err = perf_session__write_header(perf_stat.session, evsel_list,
0958 fd, false);
0959 }
0960
0961 if (err < 0)
0962 return err;
0963
0964 err = perf_event__synthesize_stat_events(&stat_config, NULL, evsel_list,
0965 process_synthesized_event, is_pipe);
0966 if (err < 0)
0967 return err;
0968 }
0969
0970 err = enable_counters();
0971 if (err)
0972 return -1;
0973
0974
0975 if (forks)
0976 evlist__start_workload(evsel_list);
0977
0978 t0 = rdclock();
0979 clock_gettime(CLOCK_MONOTONIC, &ref_time);
0980
0981 if (forks) {
0982 if (interval || timeout || evlist__ctlfd_initialized(evsel_list))
0983 status = dispatch_events(forks, timeout, interval, ×);
0984 if (child_pid != -1) {
0985 if (timeout)
0986 kill(child_pid, SIGTERM);
0987 wait4(child_pid, &status, 0, &stat_config.ru_data);
0988 }
0989
0990 if (workload_exec_errno) {
0991 const char *emsg = str_error_r(workload_exec_errno, msg, sizeof(msg));
0992 pr_err("Workload failed: %s\n", emsg);
0993 return -1;
0994 }
0995
0996 if (WIFSIGNALED(status))
0997 psignal(WTERMSIG(status), argv[0]);
0998 } else {
0999 status = dispatch_events(forks, timeout, interval, ×);
1000 }
1001
1002 disable_counters();
1003
1004 t1 = rdclock();
1005
1006 if (stat_config.walltime_run_table)
1007 stat_config.walltime_run[run_idx] = t1 - t0;
1008
1009 if (interval && stat_config.summary) {
1010 stat_config.interval = 0;
1011 stat_config.stop_read_counter = true;
1012 init_stats(&walltime_nsecs_stats);
1013 update_stats(&walltime_nsecs_stats, t1 - t0);
1014
1015 if (stat_config.aggr_mode == AGGR_GLOBAL)
1016 evlist__save_aggr_prev_raw_counts(evsel_list);
1017
1018 evlist__copy_prev_raw_counts(evsel_list);
1019 evlist__reset_prev_raw_counts(evsel_list);
1020 runtime_stat_reset(&stat_config);
1021 perf_stat__reset_shadow_per_stat(&rt_stat);
1022 } else {
1023 update_stats(&walltime_nsecs_stats, t1 - t0);
1024 update_rusage_stats(&ru_stats, &stat_config.ru_data);
1025 }
1026
1027
1028
1029
1030
1031
1032
1033 read_counters(&(struct timespec) { .tv_nsec = t1-t0 });
1034
1035
1036
1037
1038
1039 if (!STAT_RECORD)
1040 evlist__close(evsel_list);
1041
1042 return WEXITSTATUS(status);
1043 }
1044
1045 static int run_perf_stat(int argc, const char **argv, int run_idx)
1046 {
1047 int ret;
1048
1049 if (pre_cmd) {
1050 ret = system(pre_cmd);
1051 if (ret)
1052 return ret;
1053 }
1054
1055 if (sync_run)
1056 sync();
1057
1058 ret = __run_perf_stat(argc, argv, run_idx);
1059 if (ret)
1060 return ret;
1061
1062 if (post_cmd) {
1063 ret = system(post_cmd);
1064 if (ret)
1065 return ret;
1066 }
1067
1068 return ret;
1069 }
1070
1071 static void print_counters(struct timespec *ts, int argc, const char **argv)
1072 {
1073
1074 if (STAT_RECORD && perf_stat.data.is_pipe)
1075 return;
1076 if (stat_config.quiet)
1077 return;
1078
1079 evlist__print_counters(evsel_list, &stat_config, &target, ts, argc, argv);
1080 }
1081
1082 static volatile int signr = -1;
1083
1084 static void skip_signal(int signo)
1085 {
1086 if ((child_pid == -1) || stat_config.interval)
1087 done = 1;
1088
1089 signr = signo;
1090
1091
1092
1093
1094
1095
1096 child_pid = -1;
1097 }
1098
1099 static void sig_atexit(void)
1100 {
1101 sigset_t set, oset;
1102
1103
1104
1105
1106
1107
1108
1109 sigemptyset(&set);
1110 sigaddset(&set, SIGCHLD);
1111 sigprocmask(SIG_BLOCK, &set, &oset);
1112
1113 if (child_pid != -1)
1114 kill(child_pid, SIGTERM);
1115
1116 sigprocmask(SIG_SETMASK, &oset, NULL);
1117
1118 if (signr == -1)
1119 return;
1120
1121 signal(signr, SIG_DFL);
1122 kill(getpid(), signr);
1123 }
1124
1125 void perf_stat__set_big_num(int set)
1126 {
1127 stat_config.big_num = (set != 0);
1128 }
1129
1130 void perf_stat__set_no_csv_summary(int set)
1131 {
1132 stat_config.no_csv_summary = (set != 0);
1133 }
1134
1135 static int stat__set_big_num(const struct option *opt __maybe_unused,
1136 const char *s __maybe_unused, int unset)
1137 {
1138 big_num_opt = unset ? 0 : 1;
1139 perf_stat__set_big_num(!unset);
1140 return 0;
1141 }
1142
1143 static int enable_metric_only(const struct option *opt __maybe_unused,
1144 const char *s __maybe_unused, int unset)
1145 {
1146 force_metric_only = true;
1147 stat_config.metric_only = !unset;
1148 return 0;
1149 }
1150
1151 static int parse_metric_groups(const struct option *opt,
1152 const char *str,
1153 int unset __maybe_unused)
1154 {
1155 return metricgroup__parse_groups(opt, str,
1156 stat_config.metric_no_group,
1157 stat_config.metric_no_merge,
1158 &stat_config.metric_events);
1159 }
1160
1161 static int parse_control_option(const struct option *opt,
1162 const char *str,
1163 int unset __maybe_unused)
1164 {
1165 struct perf_stat_config *config = opt->value;
1166
1167 return evlist__parse_control(str, &config->ctl_fd, &config->ctl_fd_ack, &config->ctl_fd_close);
1168 }
1169
1170 static int parse_stat_cgroups(const struct option *opt,
1171 const char *str, int unset)
1172 {
1173 if (stat_config.cgroup_list) {
1174 pr_err("--cgroup and --for-each-cgroup cannot be used together\n");
1175 return -1;
1176 }
1177
1178 return parse_cgroups(opt, str, unset);
1179 }
1180
1181 static int parse_hybrid_type(const struct option *opt,
1182 const char *str,
1183 int unset __maybe_unused)
1184 {
1185 struct evlist *evlist = *(struct evlist **)opt->value;
1186
1187 if (!list_empty(&evlist->core.entries)) {
1188 fprintf(stderr, "Must define cputype before events/metrics\n");
1189 return -1;
1190 }
1191
1192 evlist->hybrid_pmu_name = perf_pmu__hybrid_type_to_pmu(str);
1193 if (!evlist->hybrid_pmu_name) {
1194 fprintf(stderr, "--cputype %s is not supported!\n", str);
1195 return -1;
1196 }
1197
1198 return 0;
1199 }
1200
1201 static struct option stat_options[] = {
1202 OPT_BOOLEAN('T', "transaction", &transaction_run,
1203 "hardware transaction statistics"),
1204 OPT_CALLBACK('e', "event", &evsel_list, "event",
1205 "event selector. use 'perf list' to list available events",
1206 parse_events_option),
1207 OPT_CALLBACK(0, "filter", &evsel_list, "filter",
1208 "event filter", parse_filter),
1209 OPT_BOOLEAN('i', "no-inherit", &stat_config.no_inherit,
1210 "child tasks do not inherit counters"),
1211 OPT_STRING('p', "pid", &target.pid, "pid",
1212 "stat events on existing process id"),
1213 OPT_STRING('t', "tid", &target.tid, "tid",
1214 "stat events on existing thread id"),
1215 #ifdef HAVE_BPF_SKEL
1216 OPT_STRING('b', "bpf-prog", &target.bpf_str, "bpf-prog-id",
1217 "stat events on existing bpf program id"),
1218 OPT_BOOLEAN(0, "bpf-counters", &target.use_bpf,
1219 "use bpf program to count events"),
1220 OPT_STRING(0, "bpf-attr-map", &target.attr_map, "attr-map-path",
1221 "path to perf_event_attr map"),
1222 #endif
1223 OPT_BOOLEAN('a', "all-cpus", &target.system_wide,
1224 "system-wide collection from all CPUs"),
1225 OPT_BOOLEAN('g', "group", &group,
1226 "put the counters into a counter group"),
1227 OPT_BOOLEAN(0, "scale", &stat_config.scale,
1228 "Use --no-scale to disable counter scaling for multiplexing"),
1229 OPT_INCR('v', "verbose", &verbose,
1230 "be more verbose (show counter open errors, etc)"),
1231 OPT_INTEGER('r', "repeat", &stat_config.run_count,
1232 "repeat command and print average + stddev (max: 100, forever: 0)"),
1233 OPT_BOOLEAN(0, "table", &stat_config.walltime_run_table,
1234 "display details about each run (only with -r option)"),
1235 OPT_BOOLEAN('n', "null", &stat_config.null_run,
1236 "null run - dont start any counters"),
1237 OPT_INCR('d', "detailed", &detailed_run,
1238 "detailed run - start a lot of events"),
1239 OPT_BOOLEAN('S', "sync", &sync_run,
1240 "call sync() before starting a run"),
1241 OPT_CALLBACK_NOOPT('B', "big-num", NULL, NULL,
1242 "print large numbers with thousands\' separators",
1243 stat__set_big_num),
1244 OPT_STRING('C', "cpu", &target.cpu_list, "cpu",
1245 "list of cpus to monitor in system-wide"),
1246 OPT_SET_UINT('A', "no-aggr", &stat_config.aggr_mode,
1247 "disable CPU count aggregation", AGGR_NONE),
1248 OPT_BOOLEAN(0, "no-merge", &stat_config.no_merge, "Do not merge identical named events"),
1249 OPT_BOOLEAN(0, "hybrid-merge", &stat_config.hybrid_merge,
1250 "Merge identical named hybrid events"),
1251 OPT_STRING('x', "field-separator", &stat_config.csv_sep, "separator",
1252 "print counts with custom separator"),
1253 OPT_BOOLEAN('j', "json-output", &stat_config.json_output,
1254 "print counts in JSON format"),
1255 OPT_CALLBACK('G', "cgroup", &evsel_list, "name",
1256 "monitor event in cgroup name only", parse_stat_cgroups),
1257 OPT_STRING(0, "for-each-cgroup", &stat_config.cgroup_list, "name",
1258 "expand events for each cgroup"),
1259 OPT_STRING('o', "output", &output_name, "file", "output file name"),
1260 OPT_BOOLEAN(0, "append", &append_file, "append to the output file"),
1261 OPT_INTEGER(0, "log-fd", &output_fd,
1262 "log output to fd, instead of stderr"),
1263 OPT_STRING(0, "pre", &pre_cmd, "command",
1264 "command to run prior to the measured command"),
1265 OPT_STRING(0, "post", &post_cmd, "command",
1266 "command to run after to the measured command"),
1267 OPT_UINTEGER('I', "interval-print", &stat_config.interval,
1268 "print counts at regular interval in ms "
1269 "(overhead is possible for values <= 100ms)"),
1270 OPT_INTEGER(0, "interval-count", &stat_config.times,
1271 "print counts for fixed number of times"),
1272 OPT_BOOLEAN(0, "interval-clear", &stat_config.interval_clear,
1273 "clear screen in between new interval"),
1274 OPT_UINTEGER(0, "timeout", &stat_config.timeout,
1275 "stop workload and print counts after a timeout period in ms (>= 10ms)"),
1276 OPT_SET_UINT(0, "per-socket", &stat_config.aggr_mode,
1277 "aggregate counts per processor socket", AGGR_SOCKET),
1278 OPT_SET_UINT(0, "per-die", &stat_config.aggr_mode,
1279 "aggregate counts per processor die", AGGR_DIE),
1280 OPT_SET_UINT(0, "per-core", &stat_config.aggr_mode,
1281 "aggregate counts per physical processor core", AGGR_CORE),
1282 OPT_SET_UINT(0, "per-thread", &stat_config.aggr_mode,
1283 "aggregate counts per thread", AGGR_THREAD),
1284 OPT_SET_UINT(0, "per-node", &stat_config.aggr_mode,
1285 "aggregate counts per numa node", AGGR_NODE),
1286 OPT_INTEGER('D', "delay", &stat_config.initial_delay,
1287 "ms to wait before starting measurement after program start (-1: start with events disabled)"),
1288 OPT_CALLBACK_NOOPT(0, "metric-only", &stat_config.metric_only, NULL,
1289 "Only print computed metrics. No raw values", enable_metric_only),
1290 OPT_BOOLEAN(0, "metric-no-group", &stat_config.metric_no_group,
1291 "don't group metric events, impacts multiplexing"),
1292 OPT_BOOLEAN(0, "metric-no-merge", &stat_config.metric_no_merge,
1293 "don't try to share events between metrics in a group"),
1294 OPT_BOOLEAN(0, "topdown", &topdown_run,
1295 "measure top-down statistics"),
1296 OPT_UINTEGER(0, "td-level", &stat_config.topdown_level,
1297 "Set the metrics level for the top-down statistics (0: max level)"),
1298 OPT_BOOLEAN(0, "smi-cost", &smi_cost,
1299 "measure SMI cost"),
1300 OPT_CALLBACK('M', "metrics", &evsel_list, "metric/metric group list",
1301 "monitor specified metrics or metric groups (separated by ,)",
1302 parse_metric_groups),
1303 OPT_BOOLEAN_FLAG(0, "all-kernel", &stat_config.all_kernel,
1304 "Configure all used events to run in kernel space.",
1305 PARSE_OPT_EXCLUSIVE),
1306 OPT_BOOLEAN_FLAG(0, "all-user", &stat_config.all_user,
1307 "Configure all used events to run in user space.",
1308 PARSE_OPT_EXCLUSIVE),
1309 OPT_BOOLEAN(0, "percore-show-thread", &stat_config.percore_show_thread,
1310 "Use with 'percore' event qualifier to show the event "
1311 "counts of one hardware thread by sum up total hardware "
1312 "threads of same physical core"),
1313 OPT_BOOLEAN(0, "summary", &stat_config.summary,
1314 "print summary for interval mode"),
1315 OPT_BOOLEAN(0, "no-csv-summary", &stat_config.no_csv_summary,
1316 "don't print 'summary' for CSV summary output"),
1317 OPT_BOOLEAN(0, "quiet", &stat_config.quiet,
1318 "don't print output (useful with record)"),
1319 OPT_CALLBACK(0, "cputype", &evsel_list, "hybrid cpu type",
1320 "Only enable events on applying cpu with this type "
1321 "for hybrid platform (e.g. core or atom)",
1322 parse_hybrid_type),
1323 #ifdef HAVE_LIBPFM
1324 OPT_CALLBACK(0, "pfm-events", &evsel_list, "event",
1325 "libpfm4 event selector. use 'perf list' to list available events",
1326 parse_libpfm_events_option),
1327 #endif
1328 OPT_CALLBACK(0, "control", &stat_config, "fd:ctl-fd[,ack-fd] or fifo:ctl-fifo[,ack-fifo]",
1329 "Listen on ctl-fd descriptor for command to control measurement ('enable': enable events, 'disable': disable events).\n"
1330 "\t\t\t Optionally send control command completion ('ack\\n') to ack-fd descriptor.\n"
1331 "\t\t\t Alternatively, ctl-fifo / ack-fifo will be opened and used as ctl-fd / ack-fd.",
1332 parse_control_option),
1333 OPT_CALLBACK_OPTARG(0, "iostat", &evsel_list, &stat_config, "default",
1334 "measure I/O performance metrics provided by arch/platform",
1335 iostat_parse),
1336 OPT_END()
1337 };
1338
1339 static const char *const aggr_mode__string[] = {
1340 [AGGR_CORE] = "core",
1341 [AGGR_DIE] = "die",
1342 [AGGR_GLOBAL] = "global",
1343 [AGGR_NODE] = "node",
1344 [AGGR_NONE] = "none",
1345 [AGGR_SOCKET] = "socket",
1346 [AGGR_THREAD] = "thread",
1347 [AGGR_UNSET] = "unset",
1348 };
1349
1350 static struct aggr_cpu_id perf_stat__get_socket(struct perf_stat_config *config __maybe_unused,
1351 struct perf_cpu cpu)
1352 {
1353 return aggr_cpu_id__socket(cpu, NULL);
1354 }
1355
1356 static struct aggr_cpu_id perf_stat__get_die(struct perf_stat_config *config __maybe_unused,
1357 struct perf_cpu cpu)
1358 {
1359 return aggr_cpu_id__die(cpu, NULL);
1360 }
1361
1362 static struct aggr_cpu_id perf_stat__get_core(struct perf_stat_config *config __maybe_unused,
1363 struct perf_cpu cpu)
1364 {
1365 return aggr_cpu_id__core(cpu, NULL);
1366 }
1367
1368 static struct aggr_cpu_id perf_stat__get_node(struct perf_stat_config *config __maybe_unused,
1369 struct perf_cpu cpu)
1370 {
1371 return aggr_cpu_id__node(cpu, NULL);
1372 }
1373
1374 static struct aggr_cpu_id perf_stat__get_aggr(struct perf_stat_config *config,
1375 aggr_get_id_t get_id, struct perf_cpu cpu)
1376 {
1377 struct aggr_cpu_id id = aggr_cpu_id__empty();
1378
1379 if (aggr_cpu_id__is_empty(&config->cpus_aggr_map->map[cpu.cpu]))
1380 config->cpus_aggr_map->map[cpu.cpu] = get_id(config, cpu);
1381
1382 id = config->cpus_aggr_map->map[cpu.cpu];
1383 return id;
1384 }
1385
1386 static struct aggr_cpu_id perf_stat__get_socket_cached(struct perf_stat_config *config,
1387 struct perf_cpu cpu)
1388 {
1389 return perf_stat__get_aggr(config, perf_stat__get_socket, cpu);
1390 }
1391
1392 static struct aggr_cpu_id perf_stat__get_die_cached(struct perf_stat_config *config,
1393 struct perf_cpu cpu)
1394 {
1395 return perf_stat__get_aggr(config, perf_stat__get_die, cpu);
1396 }
1397
1398 static struct aggr_cpu_id perf_stat__get_core_cached(struct perf_stat_config *config,
1399 struct perf_cpu cpu)
1400 {
1401 return perf_stat__get_aggr(config, perf_stat__get_core, cpu);
1402 }
1403
1404 static struct aggr_cpu_id perf_stat__get_node_cached(struct perf_stat_config *config,
1405 struct perf_cpu cpu)
1406 {
1407 return perf_stat__get_aggr(config, perf_stat__get_node, cpu);
1408 }
1409
1410 static bool term_percore_set(void)
1411 {
1412 struct evsel *counter;
1413
1414 evlist__for_each_entry(evsel_list, counter) {
1415 if (counter->percore)
1416 return true;
1417 }
1418
1419 return false;
1420 }
1421
1422 static aggr_cpu_id_get_t aggr_mode__get_aggr(enum aggr_mode aggr_mode)
1423 {
1424 switch (aggr_mode) {
1425 case AGGR_SOCKET:
1426 return aggr_cpu_id__socket;
1427 case AGGR_DIE:
1428 return aggr_cpu_id__die;
1429 case AGGR_CORE:
1430 return aggr_cpu_id__core;
1431 case AGGR_NODE:
1432 return aggr_cpu_id__node;
1433 case AGGR_NONE:
1434 if (term_percore_set())
1435 return aggr_cpu_id__core;
1436
1437 return NULL;
1438 case AGGR_GLOBAL:
1439 case AGGR_THREAD:
1440 case AGGR_UNSET:
1441 case AGGR_MAX:
1442 default:
1443 return NULL;
1444 }
1445 }
1446
1447 static aggr_get_id_t aggr_mode__get_id(enum aggr_mode aggr_mode)
1448 {
1449 switch (aggr_mode) {
1450 case AGGR_SOCKET:
1451 return perf_stat__get_socket_cached;
1452 case AGGR_DIE:
1453 return perf_stat__get_die_cached;
1454 case AGGR_CORE:
1455 return perf_stat__get_core_cached;
1456 case AGGR_NODE:
1457 return perf_stat__get_node_cached;
1458 case AGGR_NONE:
1459 if (term_percore_set()) {
1460 return perf_stat__get_core_cached;
1461 }
1462 return NULL;
1463 case AGGR_GLOBAL:
1464 case AGGR_THREAD:
1465 case AGGR_UNSET:
1466 case AGGR_MAX:
1467 default:
1468 return NULL;
1469 }
1470 }
1471
1472 static int perf_stat_init_aggr_mode(void)
1473 {
1474 int nr;
1475 aggr_cpu_id_get_t get_id = aggr_mode__get_aggr(stat_config.aggr_mode);
1476
1477 if (get_id) {
1478 stat_config.aggr_map = cpu_aggr_map__new(evsel_list->core.user_requested_cpus,
1479 get_id, NULL);
1480 if (!stat_config.aggr_map) {
1481 pr_err("cannot build %s map", aggr_mode__string[stat_config.aggr_mode]);
1482 return -1;
1483 }
1484 stat_config.aggr_get_id = aggr_mode__get_id(stat_config.aggr_mode);
1485 }
1486
1487
1488
1489
1490
1491
1492 if (evsel_list->core.user_requested_cpus)
1493 nr = perf_cpu_map__max(evsel_list->core.user_requested_cpus).cpu;
1494 else
1495 nr = 0;
1496 stat_config.cpus_aggr_map = cpu_aggr_map__empty_new(nr + 1);
1497 return stat_config.cpus_aggr_map ? 0 : -ENOMEM;
1498 }
1499
1500 static void cpu_aggr_map__delete(struct cpu_aggr_map *map)
1501 {
1502 if (map) {
1503 WARN_ONCE(refcount_read(&map->refcnt) != 0,
1504 "cpu_aggr_map refcnt unbalanced\n");
1505 free(map);
1506 }
1507 }
1508
1509 static void cpu_aggr_map__put(struct cpu_aggr_map *map)
1510 {
1511 if (map && refcount_dec_and_test(&map->refcnt))
1512 cpu_aggr_map__delete(map);
1513 }
1514
1515 static void perf_stat__exit_aggr_mode(void)
1516 {
1517 cpu_aggr_map__put(stat_config.aggr_map);
1518 cpu_aggr_map__put(stat_config.cpus_aggr_map);
1519 stat_config.aggr_map = NULL;
1520 stat_config.cpus_aggr_map = NULL;
1521 }
1522
1523 static struct aggr_cpu_id perf_env__get_socket_aggr_by_cpu(struct perf_cpu cpu, void *data)
1524 {
1525 struct perf_env *env = data;
1526 struct aggr_cpu_id id = aggr_cpu_id__empty();
1527
1528 if (cpu.cpu != -1)
1529 id.socket = env->cpu[cpu.cpu].socket_id;
1530
1531 return id;
1532 }
1533
1534 static struct aggr_cpu_id perf_env__get_die_aggr_by_cpu(struct perf_cpu cpu, void *data)
1535 {
1536 struct perf_env *env = data;
1537 struct aggr_cpu_id id = aggr_cpu_id__empty();
1538
1539 if (cpu.cpu != -1) {
1540
1541
1542
1543
1544
1545 id.socket = env->cpu[cpu.cpu].socket_id;
1546 id.die = env->cpu[cpu.cpu].die_id;
1547 }
1548
1549 return id;
1550 }
1551
1552 static struct aggr_cpu_id perf_env__get_core_aggr_by_cpu(struct perf_cpu cpu, void *data)
1553 {
1554 struct perf_env *env = data;
1555 struct aggr_cpu_id id = aggr_cpu_id__empty();
1556
1557 if (cpu.cpu != -1) {
1558
1559
1560
1561
1562
1563 id.socket = env->cpu[cpu.cpu].socket_id;
1564 id.die = env->cpu[cpu.cpu].die_id;
1565 id.core = env->cpu[cpu.cpu].core_id;
1566 }
1567
1568 return id;
1569 }
1570
1571 static struct aggr_cpu_id perf_env__get_node_aggr_by_cpu(struct perf_cpu cpu, void *data)
1572 {
1573 struct aggr_cpu_id id = aggr_cpu_id__empty();
1574
1575 id.node = perf_env__numa_node(data, cpu);
1576 return id;
1577 }
1578
1579 static struct aggr_cpu_id perf_stat__get_socket_file(struct perf_stat_config *config __maybe_unused,
1580 struct perf_cpu cpu)
1581 {
1582 return perf_env__get_socket_aggr_by_cpu(cpu, &perf_stat.session->header.env);
1583 }
1584 static struct aggr_cpu_id perf_stat__get_die_file(struct perf_stat_config *config __maybe_unused,
1585 struct perf_cpu cpu)
1586 {
1587 return perf_env__get_die_aggr_by_cpu(cpu, &perf_stat.session->header.env);
1588 }
1589
1590 static struct aggr_cpu_id perf_stat__get_core_file(struct perf_stat_config *config __maybe_unused,
1591 struct perf_cpu cpu)
1592 {
1593 return perf_env__get_core_aggr_by_cpu(cpu, &perf_stat.session->header.env);
1594 }
1595
1596 static struct aggr_cpu_id perf_stat__get_node_file(struct perf_stat_config *config __maybe_unused,
1597 struct perf_cpu cpu)
1598 {
1599 return perf_env__get_node_aggr_by_cpu(cpu, &perf_stat.session->header.env);
1600 }
1601
1602 static aggr_cpu_id_get_t aggr_mode__get_aggr_file(enum aggr_mode aggr_mode)
1603 {
1604 switch (aggr_mode) {
1605 case AGGR_SOCKET:
1606 return perf_env__get_socket_aggr_by_cpu;
1607 case AGGR_DIE:
1608 return perf_env__get_die_aggr_by_cpu;
1609 case AGGR_CORE:
1610 return perf_env__get_core_aggr_by_cpu;
1611 case AGGR_NODE:
1612 return perf_env__get_node_aggr_by_cpu;
1613 case AGGR_NONE:
1614 case AGGR_GLOBAL:
1615 case AGGR_THREAD:
1616 case AGGR_UNSET:
1617 case AGGR_MAX:
1618 default:
1619 return NULL;
1620 }
1621 }
1622
1623 static aggr_get_id_t aggr_mode__get_id_file(enum aggr_mode aggr_mode)
1624 {
1625 switch (aggr_mode) {
1626 case AGGR_SOCKET:
1627 return perf_stat__get_socket_file;
1628 case AGGR_DIE:
1629 return perf_stat__get_die_file;
1630 case AGGR_CORE:
1631 return perf_stat__get_core_file;
1632 case AGGR_NODE:
1633 return perf_stat__get_node_file;
1634 case AGGR_NONE:
1635 case AGGR_GLOBAL:
1636 case AGGR_THREAD:
1637 case AGGR_UNSET:
1638 case AGGR_MAX:
1639 default:
1640 return NULL;
1641 }
1642 }
1643
1644 static int perf_stat_init_aggr_mode_file(struct perf_stat *st)
1645 {
1646 struct perf_env *env = &st->session->header.env;
1647 aggr_cpu_id_get_t get_id = aggr_mode__get_aggr_file(stat_config.aggr_mode);
1648
1649 if (!get_id)
1650 return 0;
1651
1652 stat_config.aggr_map = cpu_aggr_map__new(evsel_list->core.user_requested_cpus, get_id, env);
1653 if (!stat_config.aggr_map) {
1654 pr_err("cannot build %s map", aggr_mode__string[stat_config.aggr_mode]);
1655 return -1;
1656 }
1657 stat_config.aggr_get_id = aggr_mode__get_id_file(stat_config.aggr_mode);
1658 return 0;
1659 }
1660
1661
1662
1663
1664
1665 static int add_default_attributes(void)
1666 {
1667 int err;
1668 struct perf_event_attr default_attrs0[] = {
1669
1670 { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_TASK_CLOCK },
1671 { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_CONTEXT_SWITCHES },
1672 { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_CPU_MIGRATIONS },
1673 { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_PAGE_FAULTS },
1674
1675 { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_CPU_CYCLES },
1676 };
1677 struct perf_event_attr frontend_attrs[] = {
1678 { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_STALLED_CYCLES_FRONTEND },
1679 };
1680 struct perf_event_attr backend_attrs[] = {
1681 { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_STALLED_CYCLES_BACKEND },
1682 };
1683 struct perf_event_attr default_attrs1[] = {
1684 { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_INSTRUCTIONS },
1685 { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_BRANCH_INSTRUCTIONS },
1686 { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_BRANCH_MISSES },
1687
1688 };
1689
1690
1691
1692
1693 struct perf_event_attr detailed_attrs[] = {
1694
1695 { .type = PERF_TYPE_HW_CACHE,
1696 .config =
1697 PERF_COUNT_HW_CACHE_L1D << 0 |
1698 (PERF_COUNT_HW_CACHE_OP_READ << 8) |
1699 (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) },
1700
1701 { .type = PERF_TYPE_HW_CACHE,
1702 .config =
1703 PERF_COUNT_HW_CACHE_L1D << 0 |
1704 (PERF_COUNT_HW_CACHE_OP_READ << 8) |
1705 (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) },
1706
1707 { .type = PERF_TYPE_HW_CACHE,
1708 .config =
1709 PERF_COUNT_HW_CACHE_LL << 0 |
1710 (PERF_COUNT_HW_CACHE_OP_READ << 8) |
1711 (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) },
1712
1713 { .type = PERF_TYPE_HW_CACHE,
1714 .config =
1715 PERF_COUNT_HW_CACHE_LL << 0 |
1716 (PERF_COUNT_HW_CACHE_OP_READ << 8) |
1717 (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) },
1718 };
1719
1720
1721
1722
1723 struct perf_event_attr very_detailed_attrs[] = {
1724
1725 { .type = PERF_TYPE_HW_CACHE,
1726 .config =
1727 PERF_COUNT_HW_CACHE_L1I << 0 |
1728 (PERF_COUNT_HW_CACHE_OP_READ << 8) |
1729 (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) },
1730
1731 { .type = PERF_TYPE_HW_CACHE,
1732 .config =
1733 PERF_COUNT_HW_CACHE_L1I << 0 |
1734 (PERF_COUNT_HW_CACHE_OP_READ << 8) |
1735 (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) },
1736
1737 { .type = PERF_TYPE_HW_CACHE,
1738 .config =
1739 PERF_COUNT_HW_CACHE_DTLB << 0 |
1740 (PERF_COUNT_HW_CACHE_OP_READ << 8) |
1741 (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) },
1742
1743 { .type = PERF_TYPE_HW_CACHE,
1744 .config =
1745 PERF_COUNT_HW_CACHE_DTLB << 0 |
1746 (PERF_COUNT_HW_CACHE_OP_READ << 8) |
1747 (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) },
1748
1749 { .type = PERF_TYPE_HW_CACHE,
1750 .config =
1751 PERF_COUNT_HW_CACHE_ITLB << 0 |
1752 (PERF_COUNT_HW_CACHE_OP_READ << 8) |
1753 (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) },
1754
1755 { .type = PERF_TYPE_HW_CACHE,
1756 .config =
1757 PERF_COUNT_HW_CACHE_ITLB << 0 |
1758 (PERF_COUNT_HW_CACHE_OP_READ << 8) |
1759 (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) },
1760
1761 };
1762
1763
1764
1765
1766 struct perf_event_attr very_very_detailed_attrs[] = {
1767
1768 { .type = PERF_TYPE_HW_CACHE,
1769 .config =
1770 PERF_COUNT_HW_CACHE_L1D << 0 |
1771 (PERF_COUNT_HW_CACHE_OP_PREFETCH << 8) |
1772 (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) },
1773
1774 { .type = PERF_TYPE_HW_CACHE,
1775 .config =
1776 PERF_COUNT_HW_CACHE_L1D << 0 |
1777 (PERF_COUNT_HW_CACHE_OP_PREFETCH << 8) |
1778 (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) },
1779 };
1780
1781 struct perf_event_attr default_null_attrs[] = {};
1782
1783
1784 if (stat_config.null_run)
1785 return 0;
1786
1787 if (transaction_run) {
1788 struct parse_events_error errinfo;
1789
1790
1791
1792
1793
1794 if (metricgroup__has_metric("transaction")) {
1795 struct option opt = { .value = &evsel_list };
1796
1797 return metricgroup__parse_groups(&opt, "transaction",
1798 stat_config.metric_no_group,
1799 stat_config.metric_no_merge,
1800 &stat_config.metric_events);
1801 }
1802
1803 parse_events_error__init(&errinfo);
1804 if (pmu_have_event("cpu", "cycles-ct") &&
1805 pmu_have_event("cpu", "el-start"))
1806 err = parse_events(evsel_list, transaction_attrs,
1807 &errinfo);
1808 else
1809 err = parse_events(evsel_list,
1810 transaction_limited_attrs,
1811 &errinfo);
1812 if (err) {
1813 fprintf(stderr, "Cannot set up transaction events\n");
1814 parse_events_error__print(&errinfo, transaction_attrs);
1815 }
1816 parse_events_error__exit(&errinfo);
1817 return err ? -1 : 0;
1818 }
1819
1820 if (smi_cost) {
1821 struct parse_events_error errinfo;
1822 int smi;
1823
1824 if (sysfs__read_int(FREEZE_ON_SMI_PATH, &smi) < 0) {
1825 fprintf(stderr, "freeze_on_smi is not supported.\n");
1826 return -1;
1827 }
1828
1829 if (!smi) {
1830 if (sysfs__write_int(FREEZE_ON_SMI_PATH, 1) < 0) {
1831 fprintf(stderr, "Failed to set freeze_on_smi.\n");
1832 return -1;
1833 }
1834 smi_reset = true;
1835 }
1836
1837 if (!pmu_have_event("msr", "aperf") ||
1838 !pmu_have_event("msr", "smi")) {
1839 fprintf(stderr, "To measure SMI cost, it needs "
1840 "msr/aperf/, msr/smi/ and cpu/cycles/ support\n");
1841 return -1;
1842 }
1843 if (!force_metric_only)
1844 stat_config.metric_only = true;
1845
1846 parse_events_error__init(&errinfo);
1847 err = parse_events(evsel_list, smi_cost_attrs, &errinfo);
1848 if (err) {
1849 parse_events_error__print(&errinfo, smi_cost_attrs);
1850 fprintf(stderr, "Cannot set up SMI cost events\n");
1851 }
1852 parse_events_error__exit(&errinfo);
1853 return err ? -1 : 0;
1854 }
1855
1856 if (topdown_run) {
1857 const char **metric_attrs = topdown_metric_attrs;
1858 unsigned int max_level = 1;
1859 char *str = NULL;
1860 bool warn = false;
1861 const char *pmu_name = arch_get_topdown_pmu_name(evsel_list, true);
1862
1863 if (!force_metric_only)
1864 stat_config.metric_only = true;
1865
1866 if (pmu_have_event(pmu_name, topdown_metric_L2_attrs[5])) {
1867 metric_attrs = topdown_metric_L2_attrs;
1868 max_level = 2;
1869 }
1870
1871 if (stat_config.topdown_level > max_level) {
1872 pr_err("Invalid top-down metrics level. The max level is %u.\n", max_level);
1873 return -1;
1874 } else if (!stat_config.topdown_level)
1875 stat_config.topdown_level = max_level;
1876
1877 if (topdown_filter_events(metric_attrs, &str, 1, pmu_name) < 0) {
1878 pr_err("Out of memory\n");
1879 return -1;
1880 }
1881
1882 if (metric_attrs[0] && str) {
1883 if (!stat_config.interval && !stat_config.metric_only) {
1884 fprintf(stat_config.output,
1885 "Topdown accuracy may decrease when measuring long periods.\n"
1886 "Please print the result regularly, e.g. -I1000\n");
1887 }
1888 goto setup_metrics;
1889 }
1890
1891 zfree(&str);
1892
1893 if (stat_config.aggr_mode != AGGR_GLOBAL &&
1894 stat_config.aggr_mode != AGGR_CORE) {
1895 pr_err("top down event configuration requires --per-core mode\n");
1896 return -1;
1897 }
1898 stat_config.aggr_mode = AGGR_CORE;
1899 if (nr_cgroups || !target__has_cpu(&target)) {
1900 pr_err("top down event configuration requires system-wide mode (-a)\n");
1901 return -1;
1902 }
1903
1904 if (topdown_filter_events(topdown_attrs, &str,
1905 arch_topdown_check_group(&warn),
1906 pmu_name) < 0) {
1907 pr_err("Out of memory\n");
1908 return -1;
1909 }
1910
1911 if (topdown_attrs[0] && str) {
1912 struct parse_events_error errinfo;
1913 if (warn)
1914 arch_topdown_group_warn();
1915 setup_metrics:
1916 parse_events_error__init(&errinfo);
1917 err = parse_events(evsel_list, str, &errinfo);
1918 if (err) {
1919 fprintf(stderr,
1920 "Cannot set up top down events %s: %d\n",
1921 str, err);
1922 parse_events_error__print(&errinfo, str);
1923 parse_events_error__exit(&errinfo);
1924 free(str);
1925 return -1;
1926 }
1927 parse_events_error__exit(&errinfo);
1928 } else {
1929 fprintf(stderr, "System does not support topdown\n");
1930 return -1;
1931 }
1932 free(str);
1933 }
1934
1935 if (!stat_config.topdown_level)
1936 stat_config.topdown_level = TOPDOWN_MAX_LEVEL;
1937
1938 if (!evsel_list->core.nr_entries) {
1939 if (target__has_cpu(&target))
1940 default_attrs0[0].config = PERF_COUNT_SW_CPU_CLOCK;
1941
1942 if (evlist__add_default_attrs(evsel_list, default_attrs0) < 0)
1943 return -1;
1944 if (pmu_have_event("cpu", "stalled-cycles-frontend")) {
1945 if (evlist__add_default_attrs(evsel_list, frontend_attrs) < 0)
1946 return -1;
1947 }
1948 if (pmu_have_event("cpu", "stalled-cycles-backend")) {
1949 if (evlist__add_default_attrs(evsel_list, backend_attrs) < 0)
1950 return -1;
1951 }
1952 if (evlist__add_default_attrs(evsel_list, default_attrs1) < 0)
1953 return -1;
1954
1955 if (evlist__add_default_attrs(evsel_list, default_null_attrs) < 0)
1956 return -1;
1957 }
1958
1959
1960
1961 if (detailed_run < 1)
1962 return 0;
1963
1964
1965 if (evlist__add_default_attrs(evsel_list, detailed_attrs) < 0)
1966 return -1;
1967
1968 if (detailed_run < 2)
1969 return 0;
1970
1971
1972 if (evlist__add_default_attrs(evsel_list, very_detailed_attrs) < 0)
1973 return -1;
1974
1975 if (detailed_run < 3)
1976 return 0;
1977
1978
1979 return evlist__add_default_attrs(evsel_list, very_very_detailed_attrs);
1980 }
1981
1982 static const char * const stat_record_usage[] = {
1983 "perf stat record [<options>]",
1984 NULL,
1985 };
1986
1987 static void init_features(struct perf_session *session)
1988 {
1989 int feat;
1990
1991 for (feat = HEADER_FIRST_FEATURE; feat < HEADER_LAST_FEATURE; feat++)
1992 perf_header__set_feat(&session->header, feat);
1993
1994 perf_header__clear_feat(&session->header, HEADER_DIR_FORMAT);
1995 perf_header__clear_feat(&session->header, HEADER_BUILD_ID);
1996 perf_header__clear_feat(&session->header, HEADER_TRACING_DATA);
1997 perf_header__clear_feat(&session->header, HEADER_BRANCH_STACK);
1998 perf_header__clear_feat(&session->header, HEADER_AUXTRACE);
1999 }
2000
2001 static int __cmd_record(int argc, const char **argv)
2002 {
2003 struct perf_session *session;
2004 struct perf_data *data = &perf_stat.data;
2005
2006 argc = parse_options(argc, argv, stat_options, stat_record_usage,
2007 PARSE_OPT_STOP_AT_NON_OPTION);
2008
2009 if (output_name)
2010 data->path = output_name;
2011
2012 if (stat_config.run_count != 1 || forever) {
2013 pr_err("Cannot use -r option with perf stat record.\n");
2014 return -1;
2015 }
2016
2017 session = perf_session__new(data, NULL);
2018 if (IS_ERR(session)) {
2019 pr_err("Perf session creation failed\n");
2020 return PTR_ERR(session);
2021 }
2022
2023 init_features(session);
2024
2025 session->evlist = evsel_list;
2026 perf_stat.session = session;
2027 perf_stat.record = true;
2028 return argc;
2029 }
2030
2031 static int process_stat_round_event(struct perf_session *session,
2032 union perf_event *event)
2033 {
2034 struct perf_record_stat_round *stat_round = &event->stat_round;
2035 struct evsel *counter;
2036 struct timespec tsh, *ts = NULL;
2037 const char **argv = session->header.env.cmdline_argv;
2038 int argc = session->header.env.nr_cmdline;
2039
2040 evlist__for_each_entry(evsel_list, counter)
2041 perf_stat_process_counter(&stat_config, counter);
2042
2043 if (stat_round->type == PERF_STAT_ROUND_TYPE__FINAL)
2044 update_stats(&walltime_nsecs_stats, stat_round->time);
2045
2046 if (stat_config.interval && stat_round->time) {
2047 tsh.tv_sec = stat_round->time / NSEC_PER_SEC;
2048 tsh.tv_nsec = stat_round->time % NSEC_PER_SEC;
2049 ts = &tsh;
2050 }
2051
2052 print_counters(ts, argc, argv);
2053 return 0;
2054 }
2055
2056 static
2057 int process_stat_config_event(struct perf_session *session,
2058 union perf_event *event)
2059 {
2060 struct perf_tool *tool = session->tool;
2061 struct perf_stat *st = container_of(tool, struct perf_stat, tool);
2062
2063 perf_event__read_stat_config(&stat_config, &event->stat_config);
2064
2065 if (perf_cpu_map__empty(st->cpus)) {
2066 if (st->aggr_mode != AGGR_UNSET)
2067 pr_warning("warning: processing task data, aggregation mode not set\n");
2068 return 0;
2069 }
2070
2071 if (st->aggr_mode != AGGR_UNSET)
2072 stat_config.aggr_mode = st->aggr_mode;
2073
2074 if (perf_stat.data.is_pipe)
2075 perf_stat_init_aggr_mode();
2076 else
2077 perf_stat_init_aggr_mode_file(st);
2078
2079 return 0;
2080 }
2081
2082 static int set_maps(struct perf_stat *st)
2083 {
2084 if (!st->cpus || !st->threads)
2085 return 0;
2086
2087 if (WARN_ONCE(st->maps_allocated, "stats double allocation\n"))
2088 return -EINVAL;
2089
2090 perf_evlist__set_maps(&evsel_list->core, st->cpus, st->threads);
2091
2092 if (evlist__alloc_stats(evsel_list, true))
2093 return -ENOMEM;
2094
2095 st->maps_allocated = true;
2096 return 0;
2097 }
2098
2099 static
2100 int process_thread_map_event(struct perf_session *session,
2101 union perf_event *event)
2102 {
2103 struct perf_tool *tool = session->tool;
2104 struct perf_stat *st = container_of(tool, struct perf_stat, tool);
2105
2106 if (st->threads) {
2107 pr_warning("Extra thread map event, ignoring.\n");
2108 return 0;
2109 }
2110
2111 st->threads = thread_map__new_event(&event->thread_map);
2112 if (!st->threads)
2113 return -ENOMEM;
2114
2115 return set_maps(st);
2116 }
2117
2118 static
2119 int process_cpu_map_event(struct perf_session *session,
2120 union perf_event *event)
2121 {
2122 struct perf_tool *tool = session->tool;
2123 struct perf_stat *st = container_of(tool, struct perf_stat, tool);
2124 struct perf_cpu_map *cpus;
2125
2126 if (st->cpus) {
2127 pr_warning("Extra cpu map event, ignoring.\n");
2128 return 0;
2129 }
2130
2131 cpus = cpu_map__new_data(&event->cpu_map.data);
2132 if (!cpus)
2133 return -ENOMEM;
2134
2135 st->cpus = cpus;
2136 return set_maps(st);
2137 }
2138
2139 static const char * const stat_report_usage[] = {
2140 "perf stat report [<options>]",
2141 NULL,
2142 };
2143
2144 static struct perf_stat perf_stat = {
2145 .tool = {
2146 .attr = perf_event__process_attr,
2147 .event_update = perf_event__process_event_update,
2148 .thread_map = process_thread_map_event,
2149 .cpu_map = process_cpu_map_event,
2150 .stat_config = process_stat_config_event,
2151 .stat = perf_event__process_stat_event,
2152 .stat_round = process_stat_round_event,
2153 },
2154 .aggr_mode = AGGR_UNSET,
2155 };
2156
2157 static int __cmd_report(int argc, const char **argv)
2158 {
2159 struct perf_session *session;
2160 const struct option options[] = {
2161 OPT_STRING('i', "input", &input_name, "file", "input file name"),
2162 OPT_SET_UINT(0, "per-socket", &perf_stat.aggr_mode,
2163 "aggregate counts per processor socket", AGGR_SOCKET),
2164 OPT_SET_UINT(0, "per-die", &perf_stat.aggr_mode,
2165 "aggregate counts per processor die", AGGR_DIE),
2166 OPT_SET_UINT(0, "per-core", &perf_stat.aggr_mode,
2167 "aggregate counts per physical processor core", AGGR_CORE),
2168 OPT_SET_UINT(0, "per-node", &perf_stat.aggr_mode,
2169 "aggregate counts per numa node", AGGR_NODE),
2170 OPT_SET_UINT('A', "no-aggr", &perf_stat.aggr_mode,
2171 "disable CPU count aggregation", AGGR_NONE),
2172 OPT_END()
2173 };
2174 struct stat st;
2175 int ret;
2176
2177 argc = parse_options(argc, argv, options, stat_report_usage, 0);
2178
2179 if (!input_name || !strlen(input_name)) {
2180 if (!fstat(STDIN_FILENO, &st) && S_ISFIFO(st.st_mode))
2181 input_name = "-";
2182 else
2183 input_name = "perf.data";
2184 }
2185
2186 perf_stat.data.path = input_name;
2187 perf_stat.data.mode = PERF_DATA_MODE_READ;
2188
2189 session = perf_session__new(&perf_stat.data, &perf_stat.tool);
2190 if (IS_ERR(session))
2191 return PTR_ERR(session);
2192
2193 perf_stat.session = session;
2194 stat_config.output = stderr;
2195 evsel_list = session->evlist;
2196
2197 ret = perf_session__process_events(session);
2198 if (ret)
2199 return ret;
2200
2201 perf_session__delete(session);
2202 return 0;
2203 }
2204
2205 static void setup_system_wide(int forks)
2206 {
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216 if (!target__none(&target))
2217 return;
2218
2219 if (!forks)
2220 target.system_wide = true;
2221 else {
2222 struct evsel *counter;
2223
2224 evlist__for_each_entry(evsel_list, counter) {
2225 if (!counter->core.requires_cpu &&
2226 strcmp(counter->name, "duration_time")) {
2227 return;
2228 }
2229 }
2230
2231 if (evsel_list->core.nr_entries)
2232 target.system_wide = true;
2233 }
2234 }
2235
2236 int cmd_stat(int argc, const char **argv)
2237 {
2238 const char * const stat_usage[] = {
2239 "perf stat [<options>] [<command>]",
2240 NULL
2241 };
2242 int status = -EINVAL, run_idx, err;
2243 const char *mode;
2244 FILE *output = stderr;
2245 unsigned int interval, timeout;
2246 const char * const stat_subcommands[] = { "record", "report" };
2247 char errbuf[BUFSIZ];
2248
2249 setlocale(LC_ALL, "");
2250
2251 evsel_list = evlist__new();
2252 if (evsel_list == NULL)
2253 return -ENOMEM;
2254
2255 parse_events__shrink_config_terms();
2256
2257
2258 set_option_flag(stat_options, 'e', "event", PARSE_OPT_NONEG);
2259 set_option_flag(stat_options, 'M', "metrics", PARSE_OPT_NONEG);
2260 set_option_flag(stat_options, 'G', "cgroup", PARSE_OPT_NONEG);
2261
2262 argc = parse_options_subcommand(argc, argv, stat_options, stat_subcommands,
2263 (const char **) stat_usage,
2264 PARSE_OPT_STOP_AT_NON_OPTION);
2265 perf_stat__collect_metric_expr(evsel_list);
2266 perf_stat__init_shadow_stats();
2267
2268 if (stat_config.csv_sep) {
2269 stat_config.csv_output = true;
2270 if (!strcmp(stat_config.csv_sep, "\\t"))
2271 stat_config.csv_sep = "\t";
2272 } else
2273 stat_config.csv_sep = DEFAULT_SEPARATOR;
2274
2275 if (argc && strlen(argv[0]) > 2 && strstarts("record", argv[0])) {
2276 argc = __cmd_record(argc, argv);
2277 if (argc < 0)
2278 return -1;
2279 } else if (argc && strlen(argv[0]) > 2 && strstarts("report", argv[0]))
2280 return __cmd_report(argc, argv);
2281
2282 interval = stat_config.interval;
2283 timeout = stat_config.timeout;
2284
2285
2286
2287
2288 if (!STAT_RECORD && output_name && strcmp(output_name, "-"))
2289 output = NULL;
2290
2291 if (output_name && output_fd) {
2292 fprintf(stderr, "cannot use both --output and --log-fd\n");
2293 parse_options_usage(stat_usage, stat_options, "o", 1);
2294 parse_options_usage(NULL, stat_options, "log-fd", 0);
2295 goto out;
2296 }
2297
2298 if (stat_config.metric_only && stat_config.aggr_mode == AGGR_THREAD) {
2299 fprintf(stderr, "--metric-only is not supported with --per-thread\n");
2300 goto out;
2301 }
2302
2303 if (stat_config.metric_only && stat_config.run_count > 1) {
2304 fprintf(stderr, "--metric-only is not supported with -r\n");
2305 goto out;
2306 }
2307
2308 if (stat_config.walltime_run_table && stat_config.run_count <= 1) {
2309 fprintf(stderr, "--table is only supported with -r\n");
2310 parse_options_usage(stat_usage, stat_options, "r", 1);
2311 parse_options_usage(NULL, stat_options, "table", 0);
2312 goto out;
2313 }
2314
2315 if (output_fd < 0) {
2316 fprintf(stderr, "argument to --log-fd must be a > 0\n");
2317 parse_options_usage(stat_usage, stat_options, "log-fd", 0);
2318 goto out;
2319 }
2320
2321 if (!output && !stat_config.quiet) {
2322 struct timespec tm;
2323 mode = append_file ? "a" : "w";
2324
2325 output = fopen(output_name, mode);
2326 if (!output) {
2327 perror("failed to create output file");
2328 return -1;
2329 }
2330 clock_gettime(CLOCK_REALTIME, &tm);
2331 fprintf(output, "# started on %s\n", ctime(&tm.tv_sec));
2332 } else if (output_fd > 0) {
2333 mode = append_file ? "a" : "w";
2334 output = fdopen(output_fd, mode);
2335 if (!output) {
2336 perror("Failed opening logfd");
2337 return -errno;
2338 }
2339 }
2340
2341 stat_config.output = output;
2342
2343
2344
2345
2346 if (stat_config.csv_output) {
2347
2348 if (big_num_opt == 1) {
2349 fprintf(stderr, "-B option not supported with -x\n");
2350 parse_options_usage(stat_usage, stat_options, "B", 1);
2351 parse_options_usage(NULL, stat_options, "x", 1);
2352 goto out;
2353 } else
2354 stat_config.big_num = false;
2355 } else if (big_num_opt == 0)
2356 stat_config.big_num = false;
2357
2358 err = target__validate(&target);
2359 if (err) {
2360 target__strerror(&target, err, errbuf, BUFSIZ);
2361 pr_warning("%s\n", errbuf);
2362 }
2363
2364 setup_system_wide(argc);
2365
2366
2367
2368
2369
2370 if ((stat_config.run_count == 1) && target__none(&target))
2371 stat_config.ru_display = true;
2372
2373 if (stat_config.run_count < 0) {
2374 pr_err("Run count must be a positive number\n");
2375 parse_options_usage(stat_usage, stat_options, "r", 1);
2376 goto out;
2377 } else if (stat_config.run_count == 0) {
2378 forever = true;
2379 stat_config.run_count = 1;
2380 }
2381
2382 if (stat_config.walltime_run_table) {
2383 stat_config.walltime_run = zalloc(stat_config.run_count * sizeof(stat_config.walltime_run[0]));
2384 if (!stat_config.walltime_run) {
2385 pr_err("failed to setup -r option");
2386 goto out;
2387 }
2388 }
2389
2390 if ((stat_config.aggr_mode == AGGR_THREAD) &&
2391 !target__has_task(&target)) {
2392 if (!target.system_wide || target.cpu_list) {
2393 fprintf(stderr, "The --per-thread option is only "
2394 "available when monitoring via -p -t -a "
2395 "options or only --per-thread.\n");
2396 parse_options_usage(NULL, stat_options, "p", 1);
2397 parse_options_usage(NULL, stat_options, "t", 1);
2398 goto out;
2399 }
2400 }
2401
2402
2403
2404
2405
2406 if (((stat_config.aggr_mode != AGGR_GLOBAL &&
2407 stat_config.aggr_mode != AGGR_THREAD) ||
2408 (nr_cgroups || stat_config.cgroup_list)) &&
2409 !target__has_cpu(&target)) {
2410 fprintf(stderr, "both cgroup and no-aggregation "
2411 "modes only available in system-wide mode\n");
2412
2413 parse_options_usage(stat_usage, stat_options, "G", 1);
2414 parse_options_usage(NULL, stat_options, "A", 1);
2415 parse_options_usage(NULL, stat_options, "a", 1);
2416 parse_options_usage(NULL, stat_options, "for-each-cgroup", 0);
2417 goto out;
2418 }
2419
2420 if (stat_config.iostat_run) {
2421 status = iostat_prepare(evsel_list, &stat_config);
2422 if (status)
2423 goto out;
2424 if (iostat_mode == IOSTAT_LIST) {
2425 iostat_list(evsel_list, &stat_config);
2426 goto out;
2427 } else if (verbose)
2428 iostat_list(evsel_list, &stat_config);
2429 if (iostat_mode == IOSTAT_RUN && !target__has_cpu(&target))
2430 target.system_wide = true;
2431 }
2432
2433 if (add_default_attributes())
2434 goto out;
2435
2436 if (stat_config.cgroup_list) {
2437 if (nr_cgroups > 0) {
2438 pr_err("--cgroup and --for-each-cgroup cannot be used together\n");
2439 parse_options_usage(stat_usage, stat_options, "G", 1);
2440 parse_options_usage(NULL, stat_options, "for-each-cgroup", 0);
2441 goto out;
2442 }
2443
2444 if (evlist__expand_cgroup(evsel_list, stat_config.cgroup_list,
2445 &stat_config.metric_events, true) < 0) {
2446 parse_options_usage(stat_usage, stat_options,
2447 "for-each-cgroup", 0);
2448 goto out;
2449 }
2450 }
2451
2452 if ((stat_config.aggr_mode == AGGR_THREAD) && (target.system_wide))
2453 target.per_thread = true;
2454
2455 if (evlist__fix_hybrid_cpus(evsel_list, target.cpu_list)) {
2456 pr_err("failed to use cpu list %s\n", target.cpu_list);
2457 goto out;
2458 }
2459
2460 target.hybrid = perf_pmu__has_hybrid();
2461 if (evlist__create_maps(evsel_list, &target) < 0) {
2462 if (target__has_task(&target)) {
2463 pr_err("Problems finding threads of monitor\n");
2464 parse_options_usage(stat_usage, stat_options, "p", 1);
2465 parse_options_usage(NULL, stat_options, "t", 1);
2466 } else if (target__has_cpu(&target)) {
2467 perror("failed to parse CPUs map");
2468 parse_options_usage(stat_usage, stat_options, "C", 1);
2469 parse_options_usage(NULL, stat_options, "a", 1);
2470 }
2471 goto out;
2472 }
2473
2474 evlist__check_cpu_maps(evsel_list);
2475
2476
2477
2478
2479
2480 if (stat_config.aggr_mode == AGGR_THREAD) {
2481 thread_map__read_comms(evsel_list->core.threads);
2482 if (target.system_wide) {
2483 if (runtime_stat_new(&stat_config,
2484 perf_thread_map__nr(evsel_list->core.threads))) {
2485 goto out;
2486 }
2487 }
2488 }
2489
2490 if (stat_config.aggr_mode == AGGR_NODE)
2491 cpu__setup_cpunode_map();
2492
2493 if (stat_config.times && interval)
2494 interval_count = true;
2495 else if (stat_config.times && !interval) {
2496 pr_err("interval-count option should be used together with "
2497 "interval-print.\n");
2498 parse_options_usage(stat_usage, stat_options, "interval-count", 0);
2499 parse_options_usage(stat_usage, stat_options, "I", 1);
2500 goto out;
2501 }
2502
2503 if (timeout && timeout < 100) {
2504 if (timeout < 10) {
2505 pr_err("timeout must be >= 10ms.\n");
2506 parse_options_usage(stat_usage, stat_options, "timeout", 0);
2507 goto out;
2508 } else
2509 pr_warning("timeout < 100ms. "
2510 "The overhead percentage could be high in some cases. "
2511 "Please proceed with caution.\n");
2512 }
2513 if (timeout && interval) {
2514 pr_err("timeout option is not supported with interval-print.\n");
2515 parse_options_usage(stat_usage, stat_options, "timeout", 0);
2516 parse_options_usage(stat_usage, stat_options, "I", 1);
2517 goto out;
2518 }
2519
2520 if (evlist__alloc_stats(evsel_list, interval))
2521 goto out;
2522
2523 if (perf_stat_init_aggr_mode())
2524 goto out;
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535 stat_config.identifier = !(STAT_RECORD && perf_stat.data.is_pipe);
2536
2537
2538
2539
2540
2541
2542
2543 atexit(sig_atexit);
2544 if (!forever)
2545 signal(SIGINT, skip_signal);
2546 signal(SIGCHLD, skip_signal);
2547 signal(SIGALRM, skip_signal);
2548 signal(SIGABRT, skip_signal);
2549
2550 if (evlist__initialize_ctlfd(evsel_list, stat_config.ctl_fd, stat_config.ctl_fd_ack))
2551 goto out;
2552
2553
2554 evlist__first(evsel_list)->ignore_missing_thread = target.pid;
2555 status = 0;
2556 for (run_idx = 0; forever || run_idx < stat_config.run_count; run_idx++) {
2557 if (stat_config.run_count != 1 && verbose > 0)
2558 fprintf(output, "[ perf stat: executing run #%d ... ]\n",
2559 run_idx + 1);
2560
2561 if (run_idx != 0)
2562 evlist__reset_prev_raw_counts(evsel_list);
2563
2564 status = run_perf_stat(argc, argv, run_idx);
2565 if (forever && status != -1 && !interval) {
2566 print_counters(NULL, argc, argv);
2567 perf_stat__reset_stats();
2568 }
2569 }
2570
2571 if (!forever && status != -1 && (!interval || stat_config.summary))
2572 print_counters(NULL, argc, argv);
2573
2574 evlist__finalize_ctlfd(evsel_list);
2575
2576 if (STAT_RECORD) {
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589 int fd = perf_data__fd(&perf_stat.data);
2590
2591 err = perf_event__synthesize_kernel_mmap((void *)&perf_stat,
2592 process_synthesized_event,
2593 &perf_stat.session->machines.host);
2594 if (err) {
2595 pr_warning("Couldn't synthesize the kernel mmap record, harmless, "
2596 "older tools may produce warnings about this file\n.");
2597 }
2598
2599 if (!interval) {
2600 if (WRITE_STAT_ROUND_EVENT(walltime_nsecs_stats.max, FINAL))
2601 pr_err("failed to write stat round event\n");
2602 }
2603
2604 if (!perf_stat.data.is_pipe) {
2605 perf_stat.session->header.data_size += perf_stat.bytes_written;
2606 perf_session__write_header(perf_stat.session, evsel_list, fd, true);
2607 }
2608
2609 evlist__close(evsel_list);
2610 perf_session__delete(perf_stat.session);
2611 }
2612
2613 perf_stat__exit_aggr_mode();
2614 evlist__free_stats(evsel_list);
2615 out:
2616 if (stat_config.iostat_run)
2617 iostat_release(evsel_list);
2618
2619 zfree(&stat_config.walltime_run);
2620
2621 if (smi_cost && smi_reset)
2622 sysfs__write_int(FREEZE_ON_SMI_PATH, 0);
2623
2624 evlist__delete(evsel_list);
2625
2626 metricgroup__rblist_exit(&stat_config.metric_events);
2627 runtime_stat_delete(&stat_config);
2628 evlist__close_control(stat_config.ctl_fd, stat_config.ctl_fd_ack, &stat_config.ctl_fd_close);
2629
2630 return status;
2631 }