brintos

brintos / linux-shallow public Read only

0
0
Text · 80.5 KiB · 689a3d4 Raw
2952 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * builtin-stat.c4 *5 * Builtin stat command: Give a precise performance counters summary6 * overview about any workload, CPU or specific PID.7 *8 * Sample output:9 10   $ perf stat ./hackbench 1011 12  Time: 0.11813 14  Performance counter stats for './hackbench 10':15 16       1708.761321 task-clock                #   11.037 CPUs utilized17            41,190 context-switches          #    0.024 M/sec18             6,735 CPU-migrations            #    0.004 M/sec19            17,318 page-faults               #    0.010 M/sec20     5,205,202,243 cycles                    #    3.046 GHz21     3,856,436,920 stalled-cycles-frontend   #   74.09% frontend cycles idle22     1,600,790,871 stalled-cycles-backend    #   30.75% backend  cycles idle23     2,603,501,247 instructions              #    0.50  insns per cycle24                                             #    1.48  stalled cycles per insn25       484,357,498 branches                  #  283.455 M/sec26         6,388,934 branch-misses             #    1.32% of all branches27 28        0.154822978  seconds time elapsed29 30 *31 * Copyright (C) 2008-2011, Red Hat Inc, Ingo Molnar <mingo@redhat.com>32 *33 * Improvements and fixes by:34 *35 *   Arjan van de Ven <arjan@linux.intel.com>36 *   Yanmin Zhang <yanmin.zhang@intel.com>37 *   Wu Fengguang <fengguang.wu@intel.com>38 *   Mike Galbraith <efault@gmx.de>39 *   Paul Mackerras <paulus@samba.org>40 *   Jaswinder Singh Rajput <jaswinder@kernel.org>41 */42 43#include "builtin.h"44#include "util/cgroup.h"45#include <subcmd/parse-options.h>46#include "util/parse-events.h"47#include "util/pmus.h"48#include "util/pmu.h"49#include "util/event.h"50#include "util/evlist.h"51#include "util/evsel.h"52#include "util/debug.h"53#include "util/color.h"54#include "util/stat.h"55#include "util/header.h"56#include "util/cpumap.h"57#include "util/thread_map.h"58#include "util/counts.h"59#include "util/topdown.h"60#include "util/session.h"61#include "util/tool.h"62#include "util/string2.h"63#include "util/metricgroup.h"64#include "util/synthetic-events.h"65#include "util/target.h"66#include "util/time-utils.h"67#include "util/top.h"68#include "util/affinity.h"69#include "util/pfm.h"70#include "util/bpf_counter.h"71#include "util/iostat.h"72#include "util/util.h"73#include "util/intel-tpebs.h"74#include "asm/bug.h"75 76#include <linux/time64.h>77#include <linux/zalloc.h>78#include <api/fs/fs.h>79#include <errno.h>80#include <signal.h>81#include <stdlib.h>82#include <sys/prctl.h>83#include <inttypes.h>84#include <locale.h>85#include <math.h>86#include <sys/types.h>87#include <sys/stat.h>88#include <sys/wait.h>89#include <unistd.h>90#include <sys/time.h>91#include <sys/resource.h>92#include <linux/err.h>93 94#include <linux/ctype.h>95#include <perf/evlist.h>96#include <internal/threadmap.h>97 98#define DEFAULT_SEPARATOR	" "99#define FREEZE_ON_SMI_PATH	"devices/cpu/freeze_on_smi"100 101static void print_counters(struct timespec *ts, int argc, const char **argv);102 103static struct evlist	*evsel_list;104static struct parse_events_option_args parse_events_option_args = {105	.evlistp = &evsel_list,106};107 108static bool all_counters_use_bpf = true;109 110static struct target target = {111	.uid	= UINT_MAX,112};113 114#define METRIC_ONLY_LEN 20115 116static volatile sig_atomic_t	child_pid			= -1;117static int			detailed_run			=  0;118static bool			transaction_run;119static bool			topdown_run			= false;120static bool			smi_cost			= false;121static bool			smi_reset			= false;122static int			big_num_opt			=  -1;123static const char		*pre_cmd			= NULL;124static const char		*post_cmd			= NULL;125static bool			sync_run			= false;126static bool			forever				= false;127static bool			force_metric_only		= false;128static struct timespec		ref_time;129static bool			append_file;130static bool			interval_count;131static const char		*output_name;132static int			output_fd;133static char			*metrics;134 135struct perf_stat {136	bool			 record;137	struct perf_data	 data;138	struct perf_session	*session;139	u64			 bytes_written;140	struct perf_tool	 tool;141	bool			 maps_allocated;142	struct perf_cpu_map	*cpus;143	struct perf_thread_map *threads;144	enum aggr_mode		 aggr_mode;145	u32			 aggr_level;146};147 148static struct perf_stat		perf_stat;149#define STAT_RECORD		perf_stat.record150 151static volatile sig_atomic_t done = 0;152 153static struct perf_stat_config stat_config = {154	.aggr_mode		= AGGR_GLOBAL,155	.aggr_level		= MAX_CACHE_LVL + 1,156	.scale			= true,157	.unit_width		= 4, /* strlen("unit") */158	.run_count		= 1,159	.metric_only_len	= METRIC_ONLY_LEN,160	.walltime_nsecs_stats	= &walltime_nsecs_stats,161	.ru_stats		= &ru_stats,162	.big_num		= true,163	.ctl_fd			= -1,164	.ctl_fd_ack		= -1,165	.iostat_run		= false,166};167 168/* Options set from the command line. */169struct opt_aggr_mode {170	bool node, socket, die, cluster, cache, core, thread, no_aggr;171};172 173/* Turn command line option into most generic aggregation mode setting. */174static enum aggr_mode opt_aggr_mode_to_aggr_mode(struct opt_aggr_mode *opt_mode)175{176	enum aggr_mode mode = AGGR_GLOBAL;177 178	if (opt_mode->node)179		mode = AGGR_NODE;180	if (opt_mode->socket)181		mode = AGGR_SOCKET;182	if (opt_mode->die)183		mode = AGGR_DIE;184	if (opt_mode->cluster)185		mode = AGGR_CLUSTER;186	if (opt_mode->cache)187		mode = AGGR_CACHE;188	if (opt_mode->core)189		mode = AGGR_CORE;190	if (opt_mode->thread)191		mode = AGGR_THREAD;192	if (opt_mode->no_aggr)193		mode = AGGR_NONE;194	return mode;195}196 197static void evlist__check_cpu_maps(struct evlist *evlist)198{199	struct evsel *evsel, *warned_leader = NULL;200 201	evlist__for_each_entry(evlist, evsel) {202		struct evsel *leader = evsel__leader(evsel);203 204		/* Check that leader matches cpus with each member. */205		if (leader == evsel)206			continue;207		if (perf_cpu_map__equal(leader->core.cpus, evsel->core.cpus))208			continue;209 210		/* If there's mismatch disable the group and warn user. */211		if (warned_leader != leader) {212			char buf[200];213 214			pr_warning("WARNING: grouped events cpus do not match.\n"215				"Events with CPUs not matching the leader will "216				"be removed from the group.\n");217			evsel__group_desc(leader, buf, sizeof(buf));218			pr_warning("  %s\n", buf);219			warned_leader = leader;220		}221		if (verbose > 0) {222			char buf[200];223 224			cpu_map__snprint(leader->core.cpus, buf, sizeof(buf));225			pr_warning("     %s: %s\n", leader->name, buf);226			cpu_map__snprint(evsel->core.cpus, buf, sizeof(buf));227			pr_warning("     %s: %s\n", evsel->name, buf);228		}229 230		evsel__remove_from_group(evsel, leader);231	}232}233 234static inline void diff_timespec(struct timespec *r, struct timespec *a,235				 struct timespec *b)236{237	r->tv_sec = a->tv_sec - b->tv_sec;238	if (a->tv_nsec < b->tv_nsec) {239		r->tv_nsec = a->tv_nsec + NSEC_PER_SEC - b->tv_nsec;240		r->tv_sec--;241	} else {242		r->tv_nsec = a->tv_nsec - b->tv_nsec ;243	}244}245 246static void perf_stat__reset_stats(void)247{248	evlist__reset_stats(evsel_list);249	perf_stat__reset_shadow_stats();250}251 252static int process_synthesized_event(const struct perf_tool *tool __maybe_unused,253				     union perf_event *event,254				     struct perf_sample *sample __maybe_unused,255				     struct machine *machine __maybe_unused)256{257	if (perf_data__write(&perf_stat.data, event, event->header.size) < 0) {258		pr_err("failed to write perf data, error: %m\n");259		return -1;260	}261 262	perf_stat.bytes_written += event->header.size;263	return 0;264}265 266static int write_stat_round_event(u64 tm, u64 type)267{268	return perf_event__synthesize_stat_round(NULL, tm, type,269						 process_synthesized_event,270						 NULL);271}272 273#define WRITE_STAT_ROUND_EVENT(time, interval) \274	write_stat_round_event(time, PERF_STAT_ROUND_TYPE__ ## interval)275 276#define SID(e, x, y) xyarray__entry(e->core.sample_id, x, y)277 278static int evsel__write_stat_event(struct evsel *counter, int cpu_map_idx, u32 thread,279				   struct perf_counts_values *count)280{281	struct perf_sample_id *sid = SID(counter, cpu_map_idx, thread);282	struct perf_cpu cpu = perf_cpu_map__cpu(evsel__cpus(counter), cpu_map_idx);283 284	return perf_event__synthesize_stat(NULL, cpu, thread, sid->id, count,285					   process_synthesized_event, NULL);286}287 288static int read_single_counter(struct evsel *counter, int cpu_map_idx, int thread)289{290	int err = evsel__read_counter(counter, cpu_map_idx, thread);291 292	/*293	 * Reading user and system time will fail when the process294	 * terminates. Use the wait4 values in that case.295	 */296	if (err && cpu_map_idx == 0 &&297	    (evsel__tool_event(counter) == PERF_TOOL_USER_TIME ||298	     evsel__tool_event(counter) == PERF_TOOL_SYSTEM_TIME)) {299		u64 val, *start_time;300		struct perf_counts_values *count =301			perf_counts(counter->counts, cpu_map_idx, thread);302 303		start_time = xyarray__entry(counter->start_times, cpu_map_idx, thread);304		if (evsel__tool_event(counter) == PERF_TOOL_USER_TIME)305			val = ru_stats.ru_utime_usec_stat.mean;306		else307			val = ru_stats.ru_stime_usec_stat.mean;308		count->ena = count->run = *start_time + val;309		count->val = val;310		return 0;311	}312	return err;313}314 315/*316 * Read out the results of a single counter:317 * do not aggregate counts across CPUs in system-wide mode318 */319static int read_counter_cpu(struct evsel *counter, int cpu_map_idx)320{321	int nthreads = perf_thread_map__nr(evsel_list->core.threads);322	int thread;323 324	if (!counter->supported)325		return -ENOENT;326 327	for (thread = 0; thread < nthreads; thread++) {328		struct perf_counts_values *count;329 330		count = perf_counts(counter->counts, cpu_map_idx, thread);331 332		/*333		 * The leader's group read loads data into its group members334		 * (via evsel__read_counter()) and sets their count->loaded.335		 */336		if (!perf_counts__is_loaded(counter->counts, cpu_map_idx, thread) &&337		    read_single_counter(counter, cpu_map_idx, thread)) {338			counter->counts->scaled = -1;339			perf_counts(counter->counts, cpu_map_idx, thread)->ena = 0;340			perf_counts(counter->counts, cpu_map_idx, thread)->run = 0;341			return -1;342		}343 344		perf_counts__set_loaded(counter->counts, cpu_map_idx, thread, false);345 346		if (STAT_RECORD) {347			if (evsel__write_stat_event(counter, cpu_map_idx, thread, count)) {348				pr_err("failed to write stat event\n");349				return -1;350			}351		}352 353		if (verbose > 1) {354			fprintf(stat_config.output,355				"%s: %d: %" PRIu64 " %" PRIu64 " %" PRIu64 "\n",356					evsel__name(counter),357					perf_cpu_map__cpu(evsel__cpus(counter),358							  cpu_map_idx).cpu,359					count->val, count->ena, count->run);360		}361	}362 363	return 0;364}365 366static int read_affinity_counters(void)367{368	struct evlist_cpu_iterator evlist_cpu_itr;369	struct affinity saved_affinity, *affinity;370 371	if (all_counters_use_bpf)372		return 0;373 374	if (!target__has_cpu(&target) || target__has_per_thread(&target))375		affinity = NULL;376	else if (affinity__setup(&saved_affinity) < 0)377		return -1;378	else379		affinity = &saved_affinity;380 381	evlist__for_each_cpu(evlist_cpu_itr, evsel_list, affinity) {382		struct evsel *counter = evlist_cpu_itr.evsel;383 384		if (evsel__is_bpf(counter))385			continue;386 387		if (!counter->err)388			counter->err = read_counter_cpu(counter, evlist_cpu_itr.cpu_map_idx);389	}390	if (affinity)391		affinity__cleanup(&saved_affinity);392 393	return 0;394}395 396static int read_bpf_map_counters(void)397{398	struct evsel *counter;399	int err;400 401	evlist__for_each_entry(evsel_list, counter) {402		if (!evsel__is_bpf(counter))403			continue;404 405		err = bpf_counter__read(counter);406		if (err)407			return err;408	}409	return 0;410}411 412static int read_counters(void)413{414	if (!stat_config.stop_read_counter) {415		if (read_bpf_map_counters() ||416		    read_affinity_counters())417			return -1;418	}419	return 0;420}421 422static void process_counters(void)423{424	struct evsel *counter;425 426	evlist__for_each_entry(evsel_list, counter) {427		if (counter->err)428			pr_debug("failed to read counter %s\n", counter->name);429		if (counter->err == 0 && perf_stat_process_counter(&stat_config, counter))430			pr_warning("failed to process counter %s\n", counter->name);431		counter->err = 0;432	}433 434	perf_stat_merge_counters(&stat_config, evsel_list);435	perf_stat_process_percore(&stat_config, evsel_list);436}437 438static void process_interval(void)439{440	struct timespec ts, rs;441 442	clock_gettime(CLOCK_MONOTONIC, &ts);443	diff_timespec(&rs, &ts, &ref_time);444 445	evlist__reset_aggr_stats(evsel_list);446 447	if (read_counters() == 0)448		process_counters();449 450	if (STAT_RECORD) {451		if (WRITE_STAT_ROUND_EVENT(rs.tv_sec * NSEC_PER_SEC + rs.tv_nsec, INTERVAL))452			pr_err("failed to write stat round event\n");453	}454 455	init_stats(&walltime_nsecs_stats);456	update_stats(&walltime_nsecs_stats, stat_config.interval * 1000000ULL);457	print_counters(&rs, 0, NULL);458}459 460static bool handle_interval(unsigned int interval, int *times)461{462	if (interval) {463		process_interval();464		if (interval_count && !(--(*times)))465			return true;466	}467	return false;468}469 470static int enable_counters(void)471{472	struct evsel *evsel;473	int err;474 475	evlist__for_each_entry(evsel_list, evsel) {476		if (!evsel__is_bpf(evsel))477			continue;478 479		err = bpf_counter__enable(evsel);480		if (err)481			return err;482	}483 484	if (!target__enable_on_exec(&target)) {485		if (!all_counters_use_bpf)486			evlist__enable(evsel_list);487	}488	return 0;489}490 491static void disable_counters(void)492{493	struct evsel *counter;494 495	/*496	 * If we don't have tracee (attaching to task or cpu), counters may497	 * still be running. To get accurate group ratios, we must stop groups498	 * from counting before reading their constituent counters.499	 */500	if (!target__none(&target)) {501		evlist__for_each_entry(evsel_list, counter)502			bpf_counter__disable(counter);503		if (!all_counters_use_bpf)504			evlist__disable(evsel_list);505	}506}507 508static volatile sig_atomic_t workload_exec_errno;509 510/*511 * evlist__prepare_workload will send a SIGUSR1512 * if the fork fails, since we asked by setting its513 * want_signal to true.514 */515static void workload_exec_failed_signal(int signo __maybe_unused, siginfo_t *info,516					void *ucontext __maybe_unused)517{518	workload_exec_errno = info->si_value.sival_int;519}520 521static bool evsel__should_store_id(struct evsel *counter)522{523	return STAT_RECORD || counter->core.attr.read_format & PERF_FORMAT_ID;524}525 526static bool is_target_alive(struct target *_target,527			    struct perf_thread_map *threads)528{529	struct stat st;530	int i;531 532	if (!target__has_task(_target))533		return true;534 535	for (i = 0; i < threads->nr; i++) {536		char path[PATH_MAX];537 538		scnprintf(path, PATH_MAX, "%s/%d", procfs__mountpoint(),539			  threads->map[i].pid);540 541		if (!stat(path, &st))542			return true;543	}544 545	return false;546}547 548static void process_evlist(struct evlist *evlist, unsigned int interval)549{550	enum evlist_ctl_cmd cmd = EVLIST_CTL_CMD_UNSUPPORTED;551 552	if (evlist__ctlfd_process(evlist, &cmd) > 0) {553		switch (cmd) {554		case EVLIST_CTL_CMD_ENABLE:555			fallthrough;556		case EVLIST_CTL_CMD_DISABLE:557			if (interval)558				process_interval();559			break;560		case EVLIST_CTL_CMD_SNAPSHOT:561		case EVLIST_CTL_CMD_ACK:562		case EVLIST_CTL_CMD_UNSUPPORTED:563		case EVLIST_CTL_CMD_EVLIST:564		case EVLIST_CTL_CMD_STOP:565		case EVLIST_CTL_CMD_PING:566		default:567			break;568		}569	}570}571 572static void compute_tts(struct timespec *time_start, struct timespec *time_stop,573			int *time_to_sleep)574{575	int tts = *time_to_sleep;576	struct timespec time_diff;577 578	diff_timespec(&time_diff, time_stop, time_start);579 580	tts -= time_diff.tv_sec * MSEC_PER_SEC +581	       time_diff.tv_nsec / NSEC_PER_MSEC;582 583	if (tts < 0)584		tts = 0;585 586	*time_to_sleep = tts;587}588 589static int dispatch_events(bool forks, int timeout, int interval, int *times)590{591	int child_exited = 0, status = 0;592	int time_to_sleep, sleep_time;593	struct timespec time_start, time_stop;594 595	if (interval)596		sleep_time = interval;597	else if (timeout)598		sleep_time = timeout;599	else600		sleep_time = 1000;601 602	time_to_sleep = sleep_time;603 604	while (!done) {605		if (forks)606			child_exited = waitpid(child_pid, &status, WNOHANG);607		else608			child_exited = !is_target_alive(&target, evsel_list->core.threads) ? 1 : 0;609 610		if (child_exited)611			break;612 613		clock_gettime(CLOCK_MONOTONIC, &time_start);614		if (!(evlist__poll(evsel_list, time_to_sleep) > 0)) { /* poll timeout or EINTR */615			if (timeout || handle_interval(interval, times))616				break;617			time_to_sleep = sleep_time;618		} else { /* fd revent */619			process_evlist(evsel_list, interval);620			clock_gettime(CLOCK_MONOTONIC, &time_stop);621			compute_tts(&time_start, &time_stop, &time_to_sleep);622		}623	}624 625	return status;626}627 628enum counter_recovery {629	COUNTER_SKIP,630	COUNTER_RETRY,631	COUNTER_FATAL,632};633 634static enum counter_recovery stat_handle_error(struct evsel *counter)635{636	char msg[BUFSIZ];637	/*638	 * PPC returns ENXIO for HW counters until 2.6.37639	 * (behavior changed with commit b0a873e).640	 */641	if (errno == EINVAL || errno == ENOSYS ||642	    errno == ENOENT || errno == EOPNOTSUPP ||643	    errno == ENXIO) {644		if (verbose > 0)645			ui__warning("%s event is not supported by the kernel.\n",646				    evsel__name(counter));647		counter->supported = false;648		/*649		 * errored is a sticky flag that means one of the counter's650		 * cpu event had a problem and needs to be reexamined.651		 */652		counter->errored = true;653 654		if ((evsel__leader(counter) != counter) ||655		    !(counter->core.leader->nr_members > 1))656			return COUNTER_SKIP;657	} else if (evsel__fallback(counter, &target, errno, msg, sizeof(msg))) {658		if (verbose > 0)659			ui__warning("%s\n", msg);660		return COUNTER_RETRY;661	} else if (target__has_per_thread(&target) &&662		   evsel_list->core.threads &&663		   evsel_list->core.threads->err_thread != -1) {664		/*665		 * For global --per-thread case, skip current666		 * error thread.667		 */668		if (!thread_map__remove(evsel_list->core.threads,669					evsel_list->core.threads->err_thread)) {670			evsel_list->core.threads->err_thread = -1;671			return COUNTER_RETRY;672		}673	} else if (counter->skippable) {674		if (verbose > 0)675			ui__warning("skipping event %s that kernel failed to open .\n",676				    evsel__name(counter));677		counter->supported = false;678		counter->errored = true;679		return COUNTER_SKIP;680	}681 682	evsel__open_strerror(counter, &target, errno, msg, sizeof(msg));683	ui__error("%s\n", msg);684 685	if (child_pid != -1)686		kill(child_pid, SIGTERM);687 688	tpebs_delete();689 690	return COUNTER_FATAL;691}692 693static int __run_perf_stat(int argc, const char **argv, int run_idx)694{695	int interval = stat_config.interval;696	int times = stat_config.times;697	int timeout = stat_config.timeout;698	char msg[BUFSIZ];699	unsigned long long t0, t1;700	struct evsel *counter;701	size_t l;702	int status = 0;703	const bool forks = (argc > 0);704	bool is_pipe = STAT_RECORD ? perf_stat.data.is_pipe : false;705	struct evlist_cpu_iterator evlist_cpu_itr;706	struct affinity saved_affinity, *affinity = NULL;707	int err;708	bool second_pass = false;709 710	if (forks) {711		if (evlist__prepare_workload(evsel_list, &target, argv, is_pipe, workload_exec_failed_signal) < 0) {712			perror("failed to prepare workload");713			return -1;714		}715		child_pid = evsel_list->workload.pid;716	}717 718	if (!cpu_map__is_dummy(evsel_list->core.user_requested_cpus)) {719		if (affinity__setup(&saved_affinity) < 0)720			return -1;721		affinity = &saved_affinity;722	}723 724	evlist__for_each_entry(evsel_list, counter) {725		counter->reset_group = false;726		if (bpf_counter__load(counter, &target))727			return -1;728		if (!(evsel__is_bperf(counter)))729			all_counters_use_bpf = false;730	}731 732	evlist__reset_aggr_stats(evsel_list);733 734	evlist__for_each_cpu(evlist_cpu_itr, evsel_list, affinity) {735		counter = evlist_cpu_itr.evsel;736 737		/*738		 * bperf calls evsel__open_per_cpu() in bperf__load(), so739		 * no need to call it again here.740		 */741		if (target.use_bpf)742			break;743 744		if (counter->reset_group || counter->errored)745			continue;746		if (evsel__is_bperf(counter))747			continue;748try_again:749		if (create_perf_stat_counter(counter, &stat_config, &target,750					     evlist_cpu_itr.cpu_map_idx) < 0) {751 752			/*753			 * Weak group failed. We cannot just undo this here754			 * because earlier CPUs might be in group mode, and the kernel755			 * doesn't support mixing group and non group reads. Defer756			 * it to later.757			 * Don't close here because we're in the wrong affinity.758			 */759			if ((errno == EINVAL || errno == EBADF) &&760				evsel__leader(counter) != counter &&761				counter->weak_group) {762				evlist__reset_weak_group(evsel_list, counter, false);763				assert(counter->reset_group);764				second_pass = true;765				continue;766			}767 768			switch (stat_handle_error(counter)) {769			case COUNTER_FATAL:770				return -1;771			case COUNTER_RETRY:772				goto try_again;773			case COUNTER_SKIP:774				continue;775			default:776				break;777			}778 779		}780		counter->supported = true;781	}782 783	if (second_pass) {784		/*785		 * Now redo all the weak group after closing them,786		 * and also close errored counters.787		 */788 789		/* First close errored or weak retry */790		evlist__for_each_cpu(evlist_cpu_itr, evsel_list, affinity) {791			counter = evlist_cpu_itr.evsel;792 793			if (!counter->reset_group && !counter->errored)794				continue;795 796			perf_evsel__close_cpu(&counter->core, evlist_cpu_itr.cpu_map_idx);797		}798		/* Now reopen weak */799		evlist__for_each_cpu(evlist_cpu_itr, evsel_list, affinity) {800			counter = evlist_cpu_itr.evsel;801 802			if (!counter->reset_group)803				continue;804try_again_reset:805			pr_debug2("reopening weak %s\n", evsel__name(counter));806			if (create_perf_stat_counter(counter, &stat_config, &target,807						     evlist_cpu_itr.cpu_map_idx) < 0) {808 809				switch (stat_handle_error(counter)) {810				case COUNTER_FATAL:811					return -1;812				case COUNTER_RETRY:813					goto try_again_reset;814				case COUNTER_SKIP:815					continue;816				default:817					break;818				}819			}820			counter->supported = true;821		}822	}823	affinity__cleanup(affinity);824 825	evlist__for_each_entry(evsel_list, counter) {826		if (!counter->supported) {827			perf_evsel__free_fd(&counter->core);828			continue;829		}830 831		l = strlen(counter->unit);832		if (l > stat_config.unit_width)833			stat_config.unit_width = l;834 835		if (evsel__should_store_id(counter) &&836		    evsel__store_ids(counter, evsel_list))837			return -1;838	}839 840	if (evlist__apply_filters(evsel_list, &counter, &target)) {841		pr_err("failed to set filter \"%s\" on event %s with %d (%s)\n",842			counter->filter, evsel__name(counter), errno,843			str_error_r(errno, msg, sizeof(msg)));844		return -1;845	}846 847	if (STAT_RECORD) {848		int fd = perf_data__fd(&perf_stat.data);849 850		if (is_pipe) {851			err = perf_header__write_pipe(perf_data__fd(&perf_stat.data));852		} else {853			err = perf_session__write_header(perf_stat.session, evsel_list,854							 fd, false);855		}856 857		if (err < 0)858			return err;859 860		err = perf_event__synthesize_stat_events(&stat_config, NULL, evsel_list,861							 process_synthesized_event, is_pipe);862		if (err < 0)863			return err;864	}865 866	if (target.initial_delay) {867		pr_info(EVLIST_DISABLED_MSG);868	} else {869		err = enable_counters();870		if (err)871			return -1;872	}873 874	/* Exec the command, if any */875	if (forks)876		evlist__start_workload(evsel_list);877 878	if (target.initial_delay > 0) {879		usleep(target.initial_delay * USEC_PER_MSEC);880		err = enable_counters();881		if (err)882			return -1;883 884		pr_info(EVLIST_ENABLED_MSG);885	}886 887	t0 = rdclock();888	clock_gettime(CLOCK_MONOTONIC, &ref_time);889 890	if (forks) {891		if (interval || timeout || evlist__ctlfd_initialized(evsel_list))892			status = dispatch_events(forks, timeout, interval, &times);893		if (child_pid != -1) {894			if (timeout)895				kill(child_pid, SIGTERM);896			wait4(child_pid, &status, 0, &stat_config.ru_data);897		}898 899		if (workload_exec_errno) {900			const char *emsg = str_error_r(workload_exec_errno, msg, sizeof(msg));901			pr_err("Workload failed: %s\n", emsg);902			return -1;903		}904 905		if (WIFSIGNALED(status))906			psignal(WTERMSIG(status), argv[0]);907	} else {908		status = dispatch_events(forks, timeout, interval, &times);909	}910 911	disable_counters();912 913	t1 = rdclock();914 915	if (stat_config.walltime_run_table)916		stat_config.walltime_run[run_idx] = t1 - t0;917 918	if (interval && stat_config.summary) {919		stat_config.interval = 0;920		stat_config.stop_read_counter = true;921		init_stats(&walltime_nsecs_stats);922		update_stats(&walltime_nsecs_stats, t1 - t0);923 924		evlist__copy_prev_raw_counts(evsel_list);925		evlist__reset_prev_raw_counts(evsel_list);926		evlist__reset_aggr_stats(evsel_list);927	} else {928		update_stats(&walltime_nsecs_stats, t1 - t0);929		update_rusage_stats(&ru_stats, &stat_config.ru_data);930	}931 932	/*933	 * Closing a group leader splits the group, and as we only disable934	 * group leaders, results in remaining events becoming enabled. To935	 * avoid arbitrary skew, we must read all counters before closing any936	 * group leaders.937	 */938	if (read_counters() == 0)939		process_counters();940 941	/*942	 * We need to keep evsel_list alive, because it's processed943	 * later the evsel_list will be closed after.944	 */945	if (!STAT_RECORD)946		evlist__close(evsel_list);947 948	return WEXITSTATUS(status);949}950 951static int run_perf_stat(int argc, const char **argv, int run_idx)952{953	int ret;954 955	if (pre_cmd) {956		ret = system(pre_cmd);957		if (ret)958			return ret;959	}960 961	if (sync_run)962		sync();963 964	ret = __run_perf_stat(argc, argv, run_idx);965	if (ret)966		return ret;967 968	if (post_cmd) {969		ret = system(post_cmd);970		if (ret)971			return ret;972	}973 974	return ret;975}976 977static void print_counters(struct timespec *ts, int argc, const char **argv)978{979	/* Do not print anything if we record to the pipe. */980	if (STAT_RECORD && perf_stat.data.is_pipe)981		return;982	if (quiet)983		return;984 985	evlist__print_counters(evsel_list, &stat_config, &target, ts, argc, argv);986}987 988static volatile sig_atomic_t signr = -1;989 990static void skip_signal(int signo)991{992	if ((child_pid == -1) || stat_config.interval)993		done = 1;994 995	signr = signo;996	/*997	 * render child_pid harmless998	 * won't send SIGTERM to a random999	 * process in case of race condition1000	 * and fast PID recycling1001	 */1002	child_pid = -1;1003}1004 1005static void sig_atexit(void)1006{1007	sigset_t set, oset;1008 1009	/*1010	 * avoid race condition with SIGCHLD handler1011	 * in skip_signal() which is modifying child_pid1012	 * goal is to avoid send SIGTERM to a random1013	 * process1014	 */1015	sigemptyset(&set);1016	sigaddset(&set, SIGCHLD);1017	sigprocmask(SIG_BLOCK, &set, &oset);1018 1019	if (child_pid != -1)1020		kill(child_pid, SIGTERM);1021 1022	sigprocmask(SIG_SETMASK, &oset, NULL);1023 1024	if (signr == -1)1025		return;1026 1027	signal(signr, SIG_DFL);1028	kill(getpid(), signr);1029}1030 1031void perf_stat__set_big_num(int set)1032{1033	stat_config.big_num = (set != 0);1034}1035 1036void perf_stat__set_no_csv_summary(int set)1037{1038	stat_config.no_csv_summary = (set != 0);1039}1040 1041static int stat__set_big_num(const struct option *opt __maybe_unused,1042			     const char *s __maybe_unused, int unset)1043{1044	big_num_opt = unset ? 0 : 1;1045	perf_stat__set_big_num(!unset);1046	return 0;1047}1048 1049static int enable_metric_only(const struct option *opt __maybe_unused,1050			      const char *s __maybe_unused, int unset)1051{1052	force_metric_only = true;1053	stat_config.metric_only = !unset;1054	return 0;1055}1056 1057static int append_metric_groups(const struct option *opt __maybe_unused,1058			       const char *str,1059			       int unset __maybe_unused)1060{1061	if (metrics) {1062		char *tmp;1063 1064		if (asprintf(&tmp, "%s,%s", metrics, str) < 0)1065			return -ENOMEM;1066		free(metrics);1067		metrics = tmp;1068	} else {1069		metrics = strdup(str);1070		if (!metrics)1071			return -ENOMEM;1072	}1073	return 0;1074}1075 1076static int parse_control_option(const struct option *opt,1077				const char *str,1078				int unset __maybe_unused)1079{1080	struct perf_stat_config *config = opt->value;1081 1082	return evlist__parse_control(str, &config->ctl_fd, &config->ctl_fd_ack, &config->ctl_fd_close);1083}1084 1085static int parse_stat_cgroups(const struct option *opt,1086			      const char *str, int unset)1087{1088	if (stat_config.cgroup_list) {1089		pr_err("--cgroup and --for-each-cgroup cannot be used together\n");1090		return -1;1091	}1092 1093	return parse_cgroups(opt, str, unset);1094}1095 1096static int parse_cputype(const struct option *opt,1097			     const char *str,1098			     int unset __maybe_unused)1099{1100	const struct perf_pmu *pmu;1101	struct evlist *evlist = *(struct evlist **)opt->value;1102 1103	if (!list_empty(&evlist->core.entries)) {1104		fprintf(stderr, "Must define cputype before events/metrics\n");1105		return -1;1106	}1107 1108	pmu = perf_pmus__pmu_for_pmu_filter(str);1109	if (!pmu) {1110		fprintf(stderr, "--cputype %s is not supported!\n", str);1111		return -1;1112	}1113	parse_events_option_args.pmu_filter = pmu->name;1114 1115	return 0;1116}1117 1118static int parse_cache_level(const struct option *opt,1119			     const char *str,1120			     int unset __maybe_unused)1121{1122	int level;1123	struct opt_aggr_mode *opt_aggr_mode = (struct opt_aggr_mode *)opt->value;1124	u32 *aggr_level = (u32 *)opt->data;1125 1126	/*1127	 * If no string is specified, aggregate based on the topology of1128	 * Last Level Cache (LLC). Since the LLC level can change from1129	 * architecture to architecture, set level greater than1130	 * MAX_CACHE_LVL which will be interpreted as LLC.1131	 */1132	if (str == NULL) {1133		level = MAX_CACHE_LVL + 1;1134		goto out;1135	}1136 1137	/*1138	 * The format to specify cache level is LX or lX where X is the1139	 * cache level.1140	 */1141	if (strlen(str) != 2 || (str[0] != 'l' && str[0] != 'L')) {1142		pr_err("Cache level must be of form L[1-%d], or l[1-%d]\n",1143		       MAX_CACHE_LVL,1144		       MAX_CACHE_LVL);1145		return -EINVAL;1146	}1147 1148	level = atoi(&str[1]);1149	if (level < 1) {1150		pr_err("Cache level must be of form L[1-%d], or l[1-%d]\n",1151		       MAX_CACHE_LVL,1152		       MAX_CACHE_LVL);1153		return -EINVAL;1154	}1155 1156	if (level > MAX_CACHE_LVL) {1157		pr_err("perf only supports max cache level of %d.\n"1158		       "Consider increasing MAX_CACHE_LVL\n", MAX_CACHE_LVL);1159		return -EINVAL;1160	}1161out:1162	opt_aggr_mode->cache = true;1163	*aggr_level = level;1164	return 0;1165}1166 1167/**1168 * Calculate the cache instance ID from the map in1169 * /sys/devices/system/cpu/cpuX/cache/indexY/shared_cpu_list1170 * Cache instance ID is the first CPU reported in the shared_cpu_list file.1171 */1172static int cpu__get_cache_id_from_map(struct perf_cpu cpu, char *map)1173{1174	int id;1175	struct perf_cpu_map *cpu_map = perf_cpu_map__new(map);1176 1177	/*1178	 * If the map contains no CPU, consider the current CPU to1179	 * be the first online CPU in the cache domain else use the1180	 * first online CPU of the cache domain as the ID.1181	 */1182	id = perf_cpu_map__min(cpu_map).cpu;1183	if (id == -1)1184		id = cpu.cpu;1185 1186	/* Free the perf_cpu_map used to find the cache ID */1187	perf_cpu_map__put(cpu_map);1188 1189	return id;1190}1191 1192/**1193 * cpu__get_cache_id - Returns 0 if successful in populating the1194 * cache level and cache id. Cache level is read from1195 * /sys/devices/system/cpu/cpuX/cache/indexY/level where as cache instance ID1196 * is the first CPU reported by1197 * /sys/devices/system/cpu/cpuX/cache/indexY/shared_cpu_list1198 */1199static int cpu__get_cache_details(struct perf_cpu cpu, struct perf_cache *cache)1200{1201	int ret = 0;1202	u32 cache_level = stat_config.aggr_level;1203	struct cpu_cache_level caches[MAX_CACHE_LVL];1204	u32 i = 0, caches_cnt = 0;1205 1206	cache->cache_lvl = (cache_level > MAX_CACHE_LVL) ? 0 : cache_level;1207	cache->cache = -1;1208 1209	ret = build_caches_for_cpu(cpu.cpu, caches, &caches_cnt);1210	if (ret) {1211		/*1212		 * If caches_cnt is not 0, cpu_cache_level data1213		 * was allocated when building the topology.1214		 * Free the allocated data before returning.1215		 */1216		if (caches_cnt)1217			goto free_caches;1218 1219		return ret;1220	}1221 1222	if (!caches_cnt)1223		return -1;1224 1225	/*1226	 * Save the data for the highest level if no1227	 * level was specified by the user.1228	 */1229	if (cache_level > MAX_CACHE_LVL) {1230		int max_level_index = 0;1231 1232		for (i = 1; i < caches_cnt; ++i) {1233			if (caches[i].level > caches[max_level_index].level)1234				max_level_index = i;1235		}1236 1237		cache->cache_lvl = caches[max_level_index].level;1238		cache->cache = cpu__get_cache_id_from_map(cpu, caches[max_level_index].map);1239 1240		/* Reset i to 0 to free entire caches[] */1241		i = 0;1242		goto free_caches;1243	}1244 1245	for (i = 0; i < caches_cnt; ++i) {1246		if (caches[i].level == cache_level) {1247			cache->cache_lvl = cache_level;1248			cache->cache = cpu__get_cache_id_from_map(cpu, caches[i].map);1249		}1250 1251		cpu_cache_level__free(&caches[i]);1252	}1253 1254free_caches:1255	/*1256	 * Free all the allocated cpu_cache_level data.1257	 */1258	while (i < caches_cnt)1259		cpu_cache_level__free(&caches[i++]);1260 1261	return ret;1262}1263 1264/**1265 * aggr_cpu_id__cache - Create an aggr_cpu_id with cache instache ID, cache1266 * level, die and socket populated with the cache instache ID, cache level,1267 * die and socket for cpu. The function signature is compatible with1268 * aggr_cpu_id_get_t.1269 */1270static struct aggr_cpu_id aggr_cpu_id__cache(struct perf_cpu cpu, void *data)1271{1272	int ret;1273	struct aggr_cpu_id id;1274	struct perf_cache cache;1275 1276	id = aggr_cpu_id__die(cpu, data);1277	if (aggr_cpu_id__is_empty(&id))1278		return id;1279 1280	ret = cpu__get_cache_details(cpu, &cache);1281	if (ret)1282		return id;1283 1284	id.cache_lvl = cache.cache_lvl;1285	id.cache = cache.cache;1286	return id;1287}1288 1289static const char *const aggr_mode__string[] = {1290	[AGGR_CORE] = "core",1291	[AGGR_CACHE] = "cache",1292	[AGGR_CLUSTER] = "cluster",1293	[AGGR_DIE] = "die",1294	[AGGR_GLOBAL] = "global",1295	[AGGR_NODE] = "node",1296	[AGGR_NONE] = "none",1297	[AGGR_SOCKET] = "socket",1298	[AGGR_THREAD] = "thread",1299	[AGGR_UNSET] = "unset",1300};1301 1302static struct aggr_cpu_id perf_stat__get_socket(struct perf_stat_config *config __maybe_unused,1303						struct perf_cpu cpu)1304{1305	return aggr_cpu_id__socket(cpu, /*data=*/NULL);1306}1307 1308static struct aggr_cpu_id perf_stat__get_die(struct perf_stat_config *config __maybe_unused,1309					     struct perf_cpu cpu)1310{1311	return aggr_cpu_id__die(cpu, /*data=*/NULL);1312}1313 1314static struct aggr_cpu_id perf_stat__get_cache_id(struct perf_stat_config *config __maybe_unused,1315						  struct perf_cpu cpu)1316{1317	return aggr_cpu_id__cache(cpu, /*data=*/NULL);1318}1319 1320static struct aggr_cpu_id perf_stat__get_cluster(struct perf_stat_config *config __maybe_unused,1321						 struct perf_cpu cpu)1322{1323	return aggr_cpu_id__cluster(cpu, /*data=*/NULL);1324}1325 1326static struct aggr_cpu_id perf_stat__get_core(struct perf_stat_config *config __maybe_unused,1327					      struct perf_cpu cpu)1328{1329	return aggr_cpu_id__core(cpu, /*data=*/NULL);1330}1331 1332static struct aggr_cpu_id perf_stat__get_node(struct perf_stat_config *config __maybe_unused,1333					      struct perf_cpu cpu)1334{1335	return aggr_cpu_id__node(cpu, /*data=*/NULL);1336}1337 1338static struct aggr_cpu_id perf_stat__get_global(struct perf_stat_config *config __maybe_unused,1339						struct perf_cpu cpu)1340{1341	return aggr_cpu_id__global(cpu, /*data=*/NULL);1342}1343 1344static struct aggr_cpu_id perf_stat__get_cpu(struct perf_stat_config *config __maybe_unused,1345					     struct perf_cpu cpu)1346{1347	return aggr_cpu_id__cpu(cpu, /*data=*/NULL);1348}1349 1350static struct aggr_cpu_id perf_stat__get_aggr(struct perf_stat_config *config,1351					      aggr_get_id_t get_id, struct perf_cpu cpu)1352{1353	struct aggr_cpu_id id;1354 1355	/* per-process mode - should use global aggr mode */1356	if (cpu.cpu == -1)1357		return get_id(config, cpu);1358 1359	if (aggr_cpu_id__is_empty(&config->cpus_aggr_map->map[cpu.cpu]))1360		config->cpus_aggr_map->map[cpu.cpu] = get_id(config, cpu);1361 1362	id = config->cpus_aggr_map->map[cpu.cpu];1363	return id;1364}1365 1366static struct aggr_cpu_id perf_stat__get_socket_cached(struct perf_stat_config *config,1367						       struct perf_cpu cpu)1368{1369	return perf_stat__get_aggr(config, perf_stat__get_socket, cpu);1370}1371 1372static struct aggr_cpu_id perf_stat__get_die_cached(struct perf_stat_config *config,1373						    struct perf_cpu cpu)1374{1375	return perf_stat__get_aggr(config, perf_stat__get_die, cpu);1376}1377 1378static struct aggr_cpu_id perf_stat__get_cluster_cached(struct perf_stat_config *config,1379							struct perf_cpu cpu)1380{1381	return perf_stat__get_aggr(config, perf_stat__get_cluster, cpu);1382}1383 1384static struct aggr_cpu_id perf_stat__get_cache_id_cached(struct perf_stat_config *config,1385							 struct perf_cpu cpu)1386{1387	return perf_stat__get_aggr(config, perf_stat__get_cache_id, cpu);1388}1389 1390static struct aggr_cpu_id perf_stat__get_core_cached(struct perf_stat_config *config,1391						     struct perf_cpu cpu)1392{1393	return perf_stat__get_aggr(config, perf_stat__get_core, cpu);1394}1395 1396static struct aggr_cpu_id perf_stat__get_node_cached(struct perf_stat_config *config,1397						     struct perf_cpu cpu)1398{1399	return perf_stat__get_aggr(config, perf_stat__get_node, cpu);1400}1401 1402static struct aggr_cpu_id perf_stat__get_global_cached(struct perf_stat_config *config,1403						       struct perf_cpu cpu)1404{1405	return perf_stat__get_aggr(config, perf_stat__get_global, cpu);1406}1407 1408static struct aggr_cpu_id perf_stat__get_cpu_cached(struct perf_stat_config *config,1409						    struct perf_cpu cpu)1410{1411	return perf_stat__get_aggr(config, perf_stat__get_cpu, cpu);1412}1413 1414static aggr_cpu_id_get_t aggr_mode__get_aggr(enum aggr_mode aggr_mode)1415{1416	switch (aggr_mode) {1417	case AGGR_SOCKET:1418		return aggr_cpu_id__socket;1419	case AGGR_DIE:1420		return aggr_cpu_id__die;1421	case AGGR_CLUSTER:1422		return aggr_cpu_id__cluster;1423	case AGGR_CACHE:1424		return aggr_cpu_id__cache;1425	case AGGR_CORE:1426		return aggr_cpu_id__core;1427	case AGGR_NODE:1428		return aggr_cpu_id__node;1429	case AGGR_NONE:1430		return aggr_cpu_id__cpu;1431	case AGGR_GLOBAL:1432		return aggr_cpu_id__global;1433	case AGGR_THREAD:1434	case AGGR_UNSET:1435	case AGGR_MAX:1436	default:1437		return NULL;1438	}1439}1440 1441static aggr_get_id_t aggr_mode__get_id(enum aggr_mode aggr_mode)1442{1443	switch (aggr_mode) {1444	case AGGR_SOCKET:1445		return perf_stat__get_socket_cached;1446	case AGGR_DIE:1447		return perf_stat__get_die_cached;1448	case AGGR_CLUSTER:1449		return perf_stat__get_cluster_cached;1450	case AGGR_CACHE:1451		return perf_stat__get_cache_id_cached;1452	case AGGR_CORE:1453		return perf_stat__get_core_cached;1454	case AGGR_NODE:1455		return perf_stat__get_node_cached;1456	case AGGR_NONE:1457		return perf_stat__get_cpu_cached;1458	case AGGR_GLOBAL:1459		return perf_stat__get_global_cached;1460	case AGGR_THREAD:1461	case AGGR_UNSET:1462	case AGGR_MAX:1463	default:1464		return NULL;1465	}1466}1467 1468static int perf_stat_init_aggr_mode(void)1469{1470	int nr;1471	aggr_cpu_id_get_t get_id = aggr_mode__get_aggr(stat_config.aggr_mode);1472 1473	if (get_id) {1474		bool needs_sort = stat_config.aggr_mode != AGGR_NONE;1475		stat_config.aggr_map = cpu_aggr_map__new(evsel_list->core.user_requested_cpus,1476							 get_id, /*data=*/NULL, needs_sort);1477		if (!stat_config.aggr_map) {1478			pr_err("cannot build %s map\n", aggr_mode__string[stat_config.aggr_mode]);1479			return -1;1480		}1481		stat_config.aggr_get_id = aggr_mode__get_id(stat_config.aggr_mode);1482	}1483 1484	if (stat_config.aggr_mode == AGGR_THREAD) {1485		nr = perf_thread_map__nr(evsel_list->core.threads);1486		stat_config.aggr_map = cpu_aggr_map__empty_new(nr);1487		if (stat_config.aggr_map == NULL)1488			return -ENOMEM;1489 1490		for (int s = 0; s < nr; s++) {1491			struct aggr_cpu_id id = aggr_cpu_id__empty();1492 1493			id.thread_idx = s;1494			stat_config.aggr_map->map[s] = id;1495		}1496		return 0;1497	}1498 1499	/*1500	 * The evsel_list->cpus is the base we operate on,1501	 * taking the highest cpu number to be the size of1502	 * the aggregation translate cpumap.1503	 */1504	if (!perf_cpu_map__is_any_cpu_or_is_empty(evsel_list->core.user_requested_cpus))1505		nr = perf_cpu_map__max(evsel_list->core.user_requested_cpus).cpu;1506	else1507		nr = 0;1508	stat_config.cpus_aggr_map = cpu_aggr_map__empty_new(nr + 1);1509	return stat_config.cpus_aggr_map ? 0 : -ENOMEM;1510}1511 1512static void cpu_aggr_map__delete(struct cpu_aggr_map *map)1513{1514	free(map);1515}1516 1517static void perf_stat__exit_aggr_mode(void)1518{1519	cpu_aggr_map__delete(stat_config.aggr_map);1520	cpu_aggr_map__delete(stat_config.cpus_aggr_map);1521	stat_config.aggr_map = NULL;1522	stat_config.cpus_aggr_map = NULL;1523}1524 1525static struct aggr_cpu_id perf_env__get_socket_aggr_by_cpu(struct perf_cpu cpu, void *data)1526{1527	struct perf_env *env = data;1528	struct aggr_cpu_id id = aggr_cpu_id__empty();1529 1530	if (cpu.cpu != -1)1531		id.socket = env->cpu[cpu.cpu].socket_id;1532 1533	return id;1534}1535 1536static struct aggr_cpu_id perf_env__get_die_aggr_by_cpu(struct perf_cpu cpu, void *data)1537{1538	struct perf_env *env = data;1539	struct aggr_cpu_id id = aggr_cpu_id__empty();1540 1541	if (cpu.cpu != -1) {1542		/*1543		 * die_id is relative to socket, so start1544		 * with the socket ID and then add die to1545		 * make a unique ID.1546		 */1547		id.socket = env->cpu[cpu.cpu].socket_id;1548		id.die = env->cpu[cpu.cpu].die_id;1549	}1550 1551	return id;1552}1553 1554static void perf_env__get_cache_id_for_cpu(struct perf_cpu cpu, struct perf_env *env,1555					   u32 cache_level, struct aggr_cpu_id *id)1556{1557	int i;1558	int caches_cnt = env->caches_cnt;1559	struct cpu_cache_level *caches = env->caches;1560 1561	id->cache_lvl = (cache_level > MAX_CACHE_LVL) ? 0 : cache_level;1562	id->cache = -1;1563 1564	if (!caches_cnt)1565		return;1566 1567	for (i = caches_cnt - 1; i > -1; --i) {1568		struct perf_cpu_map *cpu_map;1569		int map_contains_cpu;1570 1571		/*1572		 * If user has not specified a level, find the fist level with1573		 * the cpu in the map. Since building the map is expensive, do1574		 * this only if levels match.1575		 */1576		if (cache_level <= MAX_CACHE_LVL && caches[i].level != cache_level)1577			continue;1578 1579		cpu_map = perf_cpu_map__new(caches[i].map);1580		map_contains_cpu = perf_cpu_map__idx(cpu_map, cpu);1581		perf_cpu_map__put(cpu_map);1582 1583		if (map_contains_cpu != -1) {1584			id->cache_lvl = caches[i].level;1585			id->cache = cpu__get_cache_id_from_map(cpu, caches[i].map);1586			return;1587		}1588	}1589}1590 1591static struct aggr_cpu_id perf_env__get_cache_aggr_by_cpu(struct perf_cpu cpu,1592							  void *data)1593{1594	struct perf_env *env = data;1595	struct aggr_cpu_id id = aggr_cpu_id__empty();1596 1597	if (cpu.cpu != -1) {1598		u32 cache_level = (perf_stat.aggr_level) ?: stat_config.aggr_level;1599 1600		id.socket = env->cpu[cpu.cpu].socket_id;1601		id.die = env->cpu[cpu.cpu].die_id;1602		perf_env__get_cache_id_for_cpu(cpu, env, cache_level, &id);1603	}1604 1605	return id;1606}1607 1608static struct aggr_cpu_id perf_env__get_cluster_aggr_by_cpu(struct perf_cpu cpu,1609							    void *data)1610{1611	struct perf_env *env = data;1612	struct aggr_cpu_id id = aggr_cpu_id__empty();1613 1614	if (cpu.cpu != -1) {1615		id.socket = env->cpu[cpu.cpu].socket_id;1616		id.die = env->cpu[cpu.cpu].die_id;1617		id.cluster = env->cpu[cpu.cpu].cluster_id;1618	}1619 1620	return id;1621}1622 1623static struct aggr_cpu_id perf_env__get_core_aggr_by_cpu(struct perf_cpu cpu, void *data)1624{1625	struct perf_env *env = data;1626	struct aggr_cpu_id id = aggr_cpu_id__empty();1627 1628	if (cpu.cpu != -1) {1629		/*1630		 * core_id is relative to socket, die and cluster, we need a1631		 * global id. So we set socket, die id, cluster id and core id.1632		 */1633		id.socket = env->cpu[cpu.cpu].socket_id;1634		id.die = env->cpu[cpu.cpu].die_id;1635		id.cluster = env->cpu[cpu.cpu].cluster_id;1636		id.core = env->cpu[cpu.cpu].core_id;1637	}1638 1639	return id;1640}1641 1642static struct aggr_cpu_id perf_env__get_cpu_aggr_by_cpu(struct perf_cpu cpu, void *data)1643{1644	struct perf_env *env = data;1645	struct aggr_cpu_id id = aggr_cpu_id__empty();1646 1647	if (cpu.cpu != -1) {1648		/*1649		 * core_id is relative to socket and die,1650		 * we need a global id. So we set1651		 * socket, die id and core id1652		 */1653		id.socket = env->cpu[cpu.cpu].socket_id;1654		id.die = env->cpu[cpu.cpu].die_id;1655		id.core = env->cpu[cpu.cpu].core_id;1656		id.cpu = cpu;1657	}1658 1659	return id;1660}1661 1662static struct aggr_cpu_id perf_env__get_node_aggr_by_cpu(struct perf_cpu cpu, void *data)1663{1664	struct aggr_cpu_id id = aggr_cpu_id__empty();1665 1666	id.node = perf_env__numa_node(data, cpu);1667	return id;1668}1669 1670static struct aggr_cpu_id perf_env__get_global_aggr_by_cpu(struct perf_cpu cpu __maybe_unused,1671							   void *data __maybe_unused)1672{1673	struct aggr_cpu_id id = aggr_cpu_id__empty();1674 1675	/* it always aggregates to the cpu 0 */1676	id.cpu = (struct perf_cpu){ .cpu = 0 };1677	return id;1678}1679 1680static struct aggr_cpu_id perf_stat__get_socket_file(struct perf_stat_config *config __maybe_unused,1681						     struct perf_cpu cpu)1682{1683	return perf_env__get_socket_aggr_by_cpu(cpu, &perf_stat.session->header.env);1684}1685static struct aggr_cpu_id perf_stat__get_die_file(struct perf_stat_config *config __maybe_unused,1686						  struct perf_cpu cpu)1687{1688	return perf_env__get_die_aggr_by_cpu(cpu, &perf_stat.session->header.env);1689}1690 1691static struct aggr_cpu_id perf_stat__get_cluster_file(struct perf_stat_config *config __maybe_unused,1692						      struct perf_cpu cpu)1693{1694	return perf_env__get_cluster_aggr_by_cpu(cpu, &perf_stat.session->header.env);1695}1696 1697static struct aggr_cpu_id perf_stat__get_cache_file(struct perf_stat_config *config __maybe_unused,1698						    struct perf_cpu cpu)1699{1700	return perf_env__get_cache_aggr_by_cpu(cpu, &perf_stat.session->header.env);1701}1702 1703static struct aggr_cpu_id perf_stat__get_core_file(struct perf_stat_config *config __maybe_unused,1704						   struct perf_cpu cpu)1705{1706	return perf_env__get_core_aggr_by_cpu(cpu, &perf_stat.session->header.env);1707}1708 1709static struct aggr_cpu_id perf_stat__get_cpu_file(struct perf_stat_config *config __maybe_unused,1710						  struct perf_cpu cpu)1711{1712	return perf_env__get_cpu_aggr_by_cpu(cpu, &perf_stat.session->header.env);1713}1714 1715static struct aggr_cpu_id perf_stat__get_node_file(struct perf_stat_config *config __maybe_unused,1716						   struct perf_cpu cpu)1717{1718	return perf_env__get_node_aggr_by_cpu(cpu, &perf_stat.session->header.env);1719}1720 1721static struct aggr_cpu_id perf_stat__get_global_file(struct perf_stat_config *config __maybe_unused,1722						     struct perf_cpu cpu)1723{1724	return perf_env__get_global_aggr_by_cpu(cpu, &perf_stat.session->header.env);1725}1726 1727static aggr_cpu_id_get_t aggr_mode__get_aggr_file(enum aggr_mode aggr_mode)1728{1729	switch (aggr_mode) {1730	case AGGR_SOCKET:1731		return perf_env__get_socket_aggr_by_cpu;1732	case AGGR_DIE:1733		return perf_env__get_die_aggr_by_cpu;1734	case AGGR_CLUSTER:1735		return perf_env__get_cluster_aggr_by_cpu;1736	case AGGR_CACHE:1737		return perf_env__get_cache_aggr_by_cpu;1738	case AGGR_CORE:1739		return perf_env__get_core_aggr_by_cpu;1740	case AGGR_NODE:1741		return perf_env__get_node_aggr_by_cpu;1742	case AGGR_GLOBAL:1743		return perf_env__get_global_aggr_by_cpu;1744	case AGGR_NONE:1745		return perf_env__get_cpu_aggr_by_cpu;1746	case AGGR_THREAD:1747	case AGGR_UNSET:1748	case AGGR_MAX:1749	default:1750		return NULL;1751	}1752}1753 1754static aggr_get_id_t aggr_mode__get_id_file(enum aggr_mode aggr_mode)1755{1756	switch (aggr_mode) {1757	case AGGR_SOCKET:1758		return perf_stat__get_socket_file;1759	case AGGR_DIE:1760		return perf_stat__get_die_file;1761	case AGGR_CLUSTER:1762		return perf_stat__get_cluster_file;1763	case AGGR_CACHE:1764		return perf_stat__get_cache_file;1765	case AGGR_CORE:1766		return perf_stat__get_core_file;1767	case AGGR_NODE:1768		return perf_stat__get_node_file;1769	case AGGR_GLOBAL:1770		return perf_stat__get_global_file;1771	case AGGR_NONE:1772		return perf_stat__get_cpu_file;1773	case AGGR_THREAD:1774	case AGGR_UNSET:1775	case AGGR_MAX:1776	default:1777		return NULL;1778	}1779}1780 1781static int perf_stat_init_aggr_mode_file(struct perf_stat *st)1782{1783	struct perf_env *env = &st->session->header.env;1784	aggr_cpu_id_get_t get_id = aggr_mode__get_aggr_file(stat_config.aggr_mode);1785	bool needs_sort = stat_config.aggr_mode != AGGR_NONE;1786 1787	if (stat_config.aggr_mode == AGGR_THREAD) {1788		int nr = perf_thread_map__nr(evsel_list->core.threads);1789 1790		stat_config.aggr_map = cpu_aggr_map__empty_new(nr);1791		if (stat_config.aggr_map == NULL)1792			return -ENOMEM;1793 1794		for (int s = 0; s < nr; s++) {1795			struct aggr_cpu_id id = aggr_cpu_id__empty();1796 1797			id.thread_idx = s;1798			stat_config.aggr_map->map[s] = id;1799		}1800		return 0;1801	}1802 1803	if (!get_id)1804		return 0;1805 1806	stat_config.aggr_map = cpu_aggr_map__new(evsel_list->core.user_requested_cpus,1807						 get_id, env, needs_sort);1808	if (!stat_config.aggr_map) {1809		pr_err("cannot build %s map\n", aggr_mode__string[stat_config.aggr_mode]);1810		return -1;1811	}1812	stat_config.aggr_get_id = aggr_mode__get_id_file(stat_config.aggr_mode);1813	return 0;1814}1815 1816/*1817 * Add default attributes, if there were no attributes specified or1818 * if -d/--detailed, -d -d or -d -d -d is used:1819 */1820static int add_default_attributes(void)1821{1822	struct perf_event_attr default_attrs0[] = {1823 1824  { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_TASK_CLOCK		},1825  { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_CONTEXT_SWITCHES	},1826  { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_CPU_MIGRATIONS		},1827  { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_PAGE_FAULTS		},1828 1829  { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_CPU_CYCLES		},1830};1831	struct perf_event_attr frontend_attrs[] = {1832  { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_STALLED_CYCLES_FRONTEND	},1833};1834	struct perf_event_attr backend_attrs[] = {1835  { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_STALLED_CYCLES_BACKEND	},1836};1837	struct perf_event_attr default_attrs1[] = {1838  { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_INSTRUCTIONS		},1839  { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_BRANCH_INSTRUCTIONS	},1840  { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_BRANCH_MISSES		},1841 1842};1843 1844/*1845 * Detailed stats (-d), covering the L1 and last level data caches:1846 */1847	struct perf_event_attr detailed_attrs[] = {1848 1849  { .type = PERF_TYPE_HW_CACHE,1850    .config =1851	 PERF_COUNT_HW_CACHE_L1D		<<  0  |1852	(PERF_COUNT_HW_CACHE_OP_READ		<<  8) |1853	(PERF_COUNT_HW_CACHE_RESULT_ACCESS	<< 16)				},1854 1855  { .type = PERF_TYPE_HW_CACHE,1856    .config =1857	 PERF_COUNT_HW_CACHE_L1D		<<  0  |1858	(PERF_COUNT_HW_CACHE_OP_READ		<<  8) |1859	(PERF_COUNT_HW_CACHE_RESULT_MISS	<< 16)				},1860 1861  { .type = PERF_TYPE_HW_CACHE,1862    .config =1863	 PERF_COUNT_HW_CACHE_LL			<<  0  |1864	(PERF_COUNT_HW_CACHE_OP_READ		<<  8) |1865	(PERF_COUNT_HW_CACHE_RESULT_ACCESS	<< 16)				},1866 1867  { .type = PERF_TYPE_HW_CACHE,1868    .config =1869	 PERF_COUNT_HW_CACHE_LL			<<  0  |1870	(PERF_COUNT_HW_CACHE_OP_READ		<<  8) |1871	(PERF_COUNT_HW_CACHE_RESULT_MISS	<< 16)				},1872};1873 1874/*1875 * Very detailed stats (-d -d), covering the instruction cache and the TLB caches:1876 */1877	struct perf_event_attr very_detailed_attrs[] = {1878 1879  { .type = PERF_TYPE_HW_CACHE,1880    .config =1881	 PERF_COUNT_HW_CACHE_L1I		<<  0  |1882	(PERF_COUNT_HW_CACHE_OP_READ		<<  8) |1883	(PERF_COUNT_HW_CACHE_RESULT_ACCESS	<< 16)				},1884 1885  { .type = PERF_TYPE_HW_CACHE,1886    .config =1887	 PERF_COUNT_HW_CACHE_L1I		<<  0  |1888	(PERF_COUNT_HW_CACHE_OP_READ		<<  8) |1889	(PERF_COUNT_HW_CACHE_RESULT_MISS	<< 16)				},1890 1891  { .type = PERF_TYPE_HW_CACHE,1892    .config =1893	 PERF_COUNT_HW_CACHE_DTLB		<<  0  |1894	(PERF_COUNT_HW_CACHE_OP_READ		<<  8) |1895	(PERF_COUNT_HW_CACHE_RESULT_ACCESS	<< 16)				},1896 1897  { .type = PERF_TYPE_HW_CACHE,1898    .config =1899	 PERF_COUNT_HW_CACHE_DTLB		<<  0  |1900	(PERF_COUNT_HW_CACHE_OP_READ		<<  8) |1901	(PERF_COUNT_HW_CACHE_RESULT_MISS	<< 16)				},1902 1903  { .type = PERF_TYPE_HW_CACHE,1904    .config =1905	 PERF_COUNT_HW_CACHE_ITLB		<<  0  |1906	(PERF_COUNT_HW_CACHE_OP_READ		<<  8) |1907	(PERF_COUNT_HW_CACHE_RESULT_ACCESS	<< 16)				},1908 1909  { .type = PERF_TYPE_HW_CACHE,1910    .config =1911	 PERF_COUNT_HW_CACHE_ITLB		<<  0  |1912	(PERF_COUNT_HW_CACHE_OP_READ		<<  8) |1913	(PERF_COUNT_HW_CACHE_RESULT_MISS	<< 16)				},1914 1915};1916 1917/*1918 * Very, very detailed stats (-d -d -d), adding prefetch events:1919 */1920	struct perf_event_attr very_very_detailed_attrs[] = {1921 1922  { .type = PERF_TYPE_HW_CACHE,1923    .config =1924	 PERF_COUNT_HW_CACHE_L1D		<<  0  |1925	(PERF_COUNT_HW_CACHE_OP_PREFETCH	<<  8) |1926	(PERF_COUNT_HW_CACHE_RESULT_ACCESS	<< 16)				},1927 1928  { .type = PERF_TYPE_HW_CACHE,1929    .config =1930	 PERF_COUNT_HW_CACHE_L1D		<<  0  |1931	(PERF_COUNT_HW_CACHE_OP_PREFETCH	<<  8) |1932	(PERF_COUNT_HW_CACHE_RESULT_MISS	<< 16)				},1933};1934 1935	struct perf_event_attr default_null_attrs[] = {};1936	const char *pmu = parse_events_option_args.pmu_filter ?: "all";1937 1938	/* Set attrs if no event is selected and !null_run: */1939	if (stat_config.null_run)1940		return 0;1941 1942	if (transaction_run) {1943		/* Handle -T as -M transaction. Once platform specific metrics1944		 * support has been added to the json files, all architectures1945		 * will use this approach. To determine transaction support1946		 * on an architecture test for such a metric name.1947		 */1948		if (!metricgroup__has_metric(pmu, "transaction")) {1949			pr_err("Missing transaction metrics\n");1950			return -1;1951		}1952		return metricgroup__parse_groups(evsel_list, pmu, "transaction",1953						stat_config.metric_no_group,1954						stat_config.metric_no_merge,1955						stat_config.metric_no_threshold,1956						stat_config.user_requested_cpu_list,1957						stat_config.system_wide,1958						stat_config.hardware_aware_grouping,1959						&stat_config.metric_events);1960	}1961 1962	if (smi_cost) {1963		int smi;1964 1965		if (sysfs__read_int(FREEZE_ON_SMI_PATH, &smi) < 0) {1966			pr_err("freeze_on_smi is not supported.\n");1967			return -1;1968		}1969 1970		if (!smi) {1971			if (sysfs__write_int(FREEZE_ON_SMI_PATH, 1) < 0) {1972				fprintf(stderr, "Failed to set freeze_on_smi.\n");1973				return -1;1974			}1975			smi_reset = true;1976		}1977 1978		if (!metricgroup__has_metric(pmu, "smi")) {1979			pr_err("Missing smi metrics\n");1980			return -1;1981		}1982 1983		if (!force_metric_only)1984			stat_config.metric_only = true;1985 1986		return metricgroup__parse_groups(evsel_list, pmu, "smi",1987						stat_config.metric_no_group,1988						stat_config.metric_no_merge,1989						stat_config.metric_no_threshold,1990						stat_config.user_requested_cpu_list,1991						stat_config.system_wide,1992						stat_config.hardware_aware_grouping,1993						&stat_config.metric_events);1994	}1995 1996	if (topdown_run) {1997		unsigned int max_level = metricgroups__topdown_max_level();1998		char str[] = "TopdownL1";1999 2000		if (!force_metric_only)2001			stat_config.metric_only = true;2002 2003		if (!max_level) {2004			pr_err("Topdown requested but the topdown metric groups aren't present.\n"2005				"(See perf list the metric groups have names like TopdownL1)\n");2006			return -1;2007		}2008		if (stat_config.topdown_level > max_level) {2009			pr_err("Invalid top-down metrics level. The max level is %u.\n", max_level);2010			return -1;2011		} else if (!stat_config.topdown_level)2012			stat_config.topdown_level = 1;2013 2014		if (!stat_config.interval && !stat_config.metric_only) {2015			fprintf(stat_config.output,2016				"Topdown accuracy may decrease when measuring long periods.\n"2017				"Please print the result regularly, e.g. -I1000\n");2018		}2019		str[8] = stat_config.topdown_level + '0';2020		if (metricgroup__parse_groups(evsel_list,2021						pmu, str,2022						/*metric_no_group=*/false,2023						/*metric_no_merge=*/false,2024						/*metric_no_threshold=*/true,2025						stat_config.user_requested_cpu_list,2026						stat_config.system_wide,2027						stat_config.hardware_aware_grouping,2028						&stat_config.metric_events) < 0)2029			return -1;2030	}2031 2032	if (!stat_config.topdown_level)2033		stat_config.topdown_level = 1;2034 2035	if (!evsel_list->core.nr_entries) {2036		/* No events so add defaults. */2037		if (target__has_cpu(&target))2038			default_attrs0[0].config = PERF_COUNT_SW_CPU_CLOCK;2039 2040		if (evlist__add_default_attrs(evsel_list, default_attrs0) < 0)2041			return -1;2042		if (perf_pmus__have_event("cpu", "stalled-cycles-frontend")) {2043			if (evlist__add_default_attrs(evsel_list, frontend_attrs) < 0)2044				return -1;2045		}2046		if (perf_pmus__have_event("cpu", "stalled-cycles-backend")) {2047			if (evlist__add_default_attrs(evsel_list, backend_attrs) < 0)2048				return -1;2049		}2050		if (evlist__add_default_attrs(evsel_list, default_attrs1) < 0)2051			return -1;2052		/*2053		 * Add TopdownL1 metrics if they exist. To minimize2054		 * multiplexing, don't request threshold computation.2055		 */2056		if (metricgroup__has_metric(pmu, "Default")) {2057			struct evlist *metric_evlist = evlist__new();2058			struct evsel *metric_evsel;2059 2060			if (!metric_evlist)2061				return -1;2062 2063			if (metricgroup__parse_groups(metric_evlist, pmu, "Default",2064							/*metric_no_group=*/false,2065							/*metric_no_merge=*/false,2066							/*metric_no_threshold=*/true,2067							stat_config.user_requested_cpu_list,2068							stat_config.system_wide,2069							stat_config.hardware_aware_grouping,2070							&stat_config.metric_events) < 0)2071				return -1;2072 2073			evlist__for_each_entry(metric_evlist, metric_evsel) {2074				metric_evsel->skippable = true;2075				metric_evsel->default_metricgroup = true;2076			}2077			evlist__splice_list_tail(evsel_list, &metric_evlist->core.entries);2078			evlist__delete(metric_evlist);2079		}2080 2081		/* Platform specific attrs */2082		if (evlist__add_default_attrs(evsel_list, default_null_attrs) < 0)2083			return -1;2084	}2085 2086	/* Detailed events get appended to the event list: */2087 2088	if (detailed_run <  1)2089		return 0;2090 2091	/* Append detailed run extra attributes: */2092	if (evlist__add_default_attrs(evsel_list, detailed_attrs) < 0)2093		return -1;2094 2095	if (detailed_run < 2)2096		return 0;2097 2098	/* Append very detailed run extra attributes: */2099	if (evlist__add_default_attrs(evsel_list, very_detailed_attrs) < 0)2100		return -1;2101 2102	if (detailed_run < 3)2103		return 0;2104 2105	/* Append very, very detailed run extra attributes: */2106	return evlist__add_default_attrs(evsel_list, very_very_detailed_attrs);2107}2108 2109static const char * const stat_record_usage[] = {2110	"perf stat record [<options>]",2111	NULL,2112};2113 2114static void init_features(struct perf_session *session)2115{2116	int feat;2117 2118	for (feat = HEADER_FIRST_FEATURE; feat < HEADER_LAST_FEATURE; feat++)2119		perf_header__set_feat(&session->header, feat);2120 2121	perf_header__clear_feat(&session->header, HEADER_DIR_FORMAT);2122	perf_header__clear_feat(&session->header, HEADER_BUILD_ID);2123	perf_header__clear_feat(&session->header, HEADER_TRACING_DATA);2124	perf_header__clear_feat(&session->header, HEADER_BRANCH_STACK);2125	perf_header__clear_feat(&session->header, HEADER_AUXTRACE);2126}2127 2128static int __cmd_record(const struct option stat_options[], struct opt_aggr_mode *opt_mode,2129			int argc, const char **argv)2130{2131	struct perf_session *session;2132	struct perf_data *data = &perf_stat.data;2133 2134	argc = parse_options(argc, argv, stat_options, stat_record_usage,2135			     PARSE_OPT_STOP_AT_NON_OPTION);2136	stat_config.aggr_mode = opt_aggr_mode_to_aggr_mode(opt_mode);2137 2138	if (output_name)2139		data->path = output_name;2140 2141	if (stat_config.run_count != 1 || forever) {2142		pr_err("Cannot use -r option with perf stat record.\n");2143		return -1;2144	}2145 2146	session = perf_session__new(data, NULL);2147	if (IS_ERR(session)) {2148		pr_err("Perf session creation failed\n");2149		return PTR_ERR(session);2150	}2151 2152	init_features(session);2153 2154	session->evlist   = evsel_list;2155	perf_stat.session = session;2156	perf_stat.record  = true;2157	return argc;2158}2159 2160static int process_stat_round_event(struct perf_session *session,2161				    union perf_event *event)2162{2163	struct perf_record_stat_round *stat_round = &event->stat_round;2164	struct timespec tsh, *ts = NULL;2165	const char **argv = session->header.env.cmdline_argv;2166	int argc = session->header.env.nr_cmdline;2167 2168	process_counters();2169 2170	if (stat_round->type == PERF_STAT_ROUND_TYPE__FINAL)2171		update_stats(&walltime_nsecs_stats, stat_round->time);2172 2173	if (stat_config.interval && stat_round->time) {2174		tsh.tv_sec  = stat_round->time / NSEC_PER_SEC;2175		tsh.tv_nsec = stat_round->time % NSEC_PER_SEC;2176		ts = &tsh;2177	}2178 2179	print_counters(ts, argc, argv);2180	return 0;2181}2182 2183static2184int process_stat_config_event(struct perf_session *session,2185			      union perf_event *event)2186{2187	const struct perf_tool *tool = session->tool;2188	struct perf_stat *st = container_of(tool, struct perf_stat, tool);2189 2190	perf_event__read_stat_config(&stat_config, &event->stat_config);2191 2192	if (perf_cpu_map__is_empty(st->cpus)) {2193		if (st->aggr_mode != AGGR_UNSET)2194			pr_warning("warning: processing task data, aggregation mode not set\n");2195	} else if (st->aggr_mode != AGGR_UNSET) {2196		stat_config.aggr_mode = st->aggr_mode;2197	}2198 2199	if (perf_stat.data.is_pipe)2200		perf_stat_init_aggr_mode();2201	else2202		perf_stat_init_aggr_mode_file(st);2203 2204	if (stat_config.aggr_map) {2205		int nr_aggr = stat_config.aggr_map->nr;2206 2207		if (evlist__alloc_aggr_stats(session->evlist, nr_aggr) < 0) {2208			pr_err("cannot allocate aggr counts\n");2209			return -1;2210		}2211	}2212	return 0;2213}2214 2215static int set_maps(struct perf_stat *st)2216{2217	if (!st->cpus || !st->threads)2218		return 0;2219 2220	if (WARN_ONCE(st->maps_allocated, "stats double allocation\n"))2221		return -EINVAL;2222 2223	perf_evlist__set_maps(&evsel_list->core, st->cpus, st->threads);2224 2225	if (evlist__alloc_stats(&stat_config, evsel_list, /*alloc_raw=*/true))2226		return -ENOMEM;2227 2228	st->maps_allocated = true;2229	return 0;2230}2231 2232static2233int process_thread_map_event(struct perf_session *session,2234			     union perf_event *event)2235{2236	const struct perf_tool *tool = session->tool;2237	struct perf_stat *st = container_of(tool, struct perf_stat, tool);2238 2239	if (st->threads) {2240		pr_warning("Extra thread map event, ignoring.\n");2241		return 0;2242	}2243 2244	st->threads = thread_map__new_event(&event->thread_map);2245	if (!st->threads)2246		return -ENOMEM;2247 2248	return set_maps(st);2249}2250 2251static2252int process_cpu_map_event(struct perf_session *session,2253			  union perf_event *event)2254{2255	const struct perf_tool *tool = session->tool;2256	struct perf_stat *st = container_of(tool, struct perf_stat, tool);2257	struct perf_cpu_map *cpus;2258 2259	if (st->cpus) {2260		pr_warning("Extra cpu map event, ignoring.\n");2261		return 0;2262	}2263 2264	cpus = cpu_map__new_data(&event->cpu_map.data);2265	if (!cpus)2266		return -ENOMEM;2267 2268	st->cpus = cpus;2269	return set_maps(st);2270}2271 2272static const char * const stat_report_usage[] = {2273	"perf stat report [<options>]",2274	NULL,2275};2276 2277static struct perf_stat perf_stat = {2278	.aggr_mode	= AGGR_UNSET,2279	.aggr_level	= 0,2280};2281 2282static int __cmd_report(int argc, const char **argv)2283{2284	struct perf_session *session;2285	const struct option options[] = {2286	OPT_STRING('i', "input", &input_name, "file", "input file name"),2287	OPT_SET_UINT(0, "per-socket", &perf_stat.aggr_mode,2288		     "aggregate counts per processor socket", AGGR_SOCKET),2289	OPT_SET_UINT(0, "per-die", &perf_stat.aggr_mode,2290		     "aggregate counts per processor die", AGGR_DIE),2291	OPT_SET_UINT(0, "per-cluster", &perf_stat.aggr_mode,2292		     "aggregate counts perf processor cluster", AGGR_CLUSTER),2293	OPT_CALLBACK_OPTARG(0, "per-cache", &perf_stat.aggr_mode, &perf_stat.aggr_level,2294			    "cache level",2295			    "aggregate count at this cache level (Default: LLC)",2296			    parse_cache_level),2297	OPT_SET_UINT(0, "per-core", &perf_stat.aggr_mode,2298		     "aggregate counts per physical processor core", AGGR_CORE),2299	OPT_SET_UINT(0, "per-node", &perf_stat.aggr_mode,2300		     "aggregate counts per numa node", AGGR_NODE),2301	OPT_SET_UINT('A', "no-aggr", &perf_stat.aggr_mode,2302		     "disable CPU count aggregation", AGGR_NONE),2303	OPT_END()2304	};2305	struct stat st;2306	int ret;2307 2308	argc = parse_options(argc, argv, options, stat_report_usage, 0);2309 2310	if (!input_name || !strlen(input_name)) {2311		if (!fstat(STDIN_FILENO, &st) && S_ISFIFO(st.st_mode))2312			input_name = "-";2313		else2314			input_name = "perf.data";2315	}2316 2317	perf_stat.data.path = input_name;2318	perf_stat.data.mode = PERF_DATA_MODE_READ;2319 2320	perf_tool__init(&perf_stat.tool, /*ordered_events=*/false);2321	perf_stat.tool.attr		= perf_event__process_attr;2322	perf_stat.tool.event_update	= perf_event__process_event_update;2323	perf_stat.tool.thread_map	= process_thread_map_event;2324	perf_stat.tool.cpu_map		= process_cpu_map_event;2325	perf_stat.tool.stat_config	= process_stat_config_event;2326	perf_stat.tool.stat		= perf_event__process_stat_event;2327	perf_stat.tool.stat_round	= process_stat_round_event;2328 2329	session = perf_session__new(&perf_stat.data, &perf_stat.tool);2330	if (IS_ERR(session))2331		return PTR_ERR(session);2332 2333	perf_stat.session  = session;2334	stat_config.output = stderr;2335	evlist__delete(evsel_list);2336	evsel_list         = session->evlist;2337 2338	ret = perf_session__process_events(session);2339	if (ret)2340		return ret;2341 2342	perf_session__delete(session);2343	return 0;2344}2345 2346static void setup_system_wide(int forks)2347{2348	/*2349	 * Make system wide (-a) the default target if2350	 * no target was specified and one of following2351	 * conditions is met:2352	 *2353	 *   - there's no workload specified2354	 *   - there is workload specified but all requested2355	 *     events are system wide events2356	 */2357	if (!target__none(&target))2358		return;2359 2360	if (!forks)2361		target.system_wide = true;2362	else {2363		struct evsel *counter;2364 2365		evlist__for_each_entry(evsel_list, counter) {2366			if (!counter->core.requires_cpu &&2367			    !evsel__name_is(counter, "duration_time")) {2368				return;2369			}2370		}2371 2372		if (evsel_list->core.nr_entries)2373			target.system_wide = true;2374	}2375}2376 2377int cmd_stat(int argc, const char **argv)2378{2379	struct opt_aggr_mode opt_mode = {};2380	struct option stat_options[] = {2381		OPT_BOOLEAN('T', "transaction", &transaction_run,2382			"hardware transaction statistics"),2383		OPT_CALLBACK('e', "event", &parse_events_option_args, "event",2384			"event selector. use 'perf list' to list available events",2385			parse_events_option),2386		OPT_CALLBACK(0, "filter", &evsel_list, "filter",2387			"event filter", parse_filter),2388		OPT_BOOLEAN('i', "no-inherit", &stat_config.no_inherit,2389			"child tasks do not inherit counters"),2390		OPT_STRING('p', "pid", &target.pid, "pid",2391			"stat events on existing process id"),2392		OPT_STRING('t', "tid", &target.tid, "tid",2393			"stat events on existing thread id"),2394#ifdef HAVE_BPF_SKEL2395		OPT_STRING('b', "bpf-prog", &target.bpf_str, "bpf-prog-id",2396			"stat events on existing bpf program id"),2397		OPT_BOOLEAN(0, "bpf-counters", &target.use_bpf,2398			"use bpf program to count events"),2399		OPT_STRING(0, "bpf-attr-map", &target.attr_map, "attr-map-path",2400			"path to perf_event_attr map"),2401#endif2402		OPT_BOOLEAN('a', "all-cpus", &target.system_wide,2403			"system-wide collection from all CPUs"),2404		OPT_BOOLEAN(0, "scale", &stat_config.scale,2405			"Use --no-scale to disable counter scaling for multiplexing"),2406		OPT_INCR('v', "verbose", &verbose,2407			"be more verbose (show counter open errors, etc)"),2408		OPT_INTEGER('r', "repeat", &stat_config.run_count,2409			"repeat command and print average + stddev (max: 100, forever: 0)"),2410		OPT_BOOLEAN(0, "table", &stat_config.walltime_run_table,2411			"display details about each run (only with -r option)"),2412		OPT_BOOLEAN('n', "null", &stat_config.null_run,2413			"null run - dont start any counters"),2414		OPT_INCR('d', "detailed", &detailed_run,2415			"detailed run - start a lot of events"),2416		OPT_BOOLEAN('S', "sync", &sync_run,2417			"call sync() before starting a run"),2418		OPT_CALLBACK_NOOPT('B', "big-num", NULL, NULL,2419				"print large numbers with thousands\' separators",2420				stat__set_big_num),2421		OPT_STRING('C', "cpu", &target.cpu_list, "cpu",2422			"list of cpus to monitor in system-wide"),2423		OPT_BOOLEAN('A', "no-aggr", &opt_mode.no_aggr,2424			"disable aggregation across CPUs or PMUs"),2425		OPT_BOOLEAN(0, "no-merge", &opt_mode.no_aggr,2426			"disable aggregation the same as -A or -no-aggr"),2427		OPT_BOOLEAN(0, "hybrid-merge", &stat_config.hybrid_merge,2428			"Merge identical named hybrid events"),2429		OPT_STRING('x', "field-separator", &stat_config.csv_sep, "separator",2430			"print counts with custom separator"),2431		OPT_BOOLEAN('j', "json-output", &stat_config.json_output,2432			"print counts in JSON format"),2433		OPT_CALLBACK('G', "cgroup", &evsel_list, "name",2434			"monitor event in cgroup name only", parse_stat_cgroups),2435		OPT_STRING(0, "for-each-cgroup", &stat_config.cgroup_list, "name",2436			"expand events for each cgroup"),2437		OPT_STRING('o', "output", &output_name, "file", "output file name"),2438		OPT_BOOLEAN(0, "append", &append_file, "append to the output file"),2439		OPT_INTEGER(0, "log-fd", &output_fd,2440			"log output to fd, instead of stderr"),2441		OPT_STRING(0, "pre", &pre_cmd, "command",2442			"command to run prior to the measured command"),2443		OPT_STRING(0, "post", &post_cmd, "command",2444			"command to run after to the measured command"),2445		OPT_UINTEGER('I', "interval-print", &stat_config.interval,2446			"print counts at regular interval in ms "2447			"(overhead is possible for values <= 100ms)"),2448		OPT_INTEGER(0, "interval-count", &stat_config.times,2449			"print counts for fixed number of times"),2450		OPT_BOOLEAN(0, "interval-clear", &stat_config.interval_clear,2451			"clear screen in between new interval"),2452		OPT_UINTEGER(0, "timeout", &stat_config.timeout,2453			"stop workload and print counts after a timeout period in ms (>= 10ms)"),2454		OPT_BOOLEAN(0, "per-socket", &opt_mode.socket,2455			"aggregate counts per processor socket"),2456		OPT_BOOLEAN(0, "per-die", &opt_mode.die, "aggregate counts per processor die"),2457		OPT_BOOLEAN(0, "per-cluster", &opt_mode.cluster,2458			"aggregate counts per processor cluster"),2459		OPT_CALLBACK_OPTARG(0, "per-cache", &opt_mode, &stat_config.aggr_level,2460				"cache level", "aggregate count at this cache level (Default: LLC)",2461				parse_cache_level),2462		OPT_BOOLEAN(0, "per-core", &opt_mode.core,2463			"aggregate counts per physical processor core"),2464		OPT_BOOLEAN(0, "per-thread", &opt_mode.thread, "aggregate counts per thread"),2465		OPT_BOOLEAN(0, "per-node", &opt_mode.node, "aggregate counts per numa node"),2466		OPT_INTEGER('D', "delay", &target.initial_delay,2467			"ms to wait before starting measurement after program start (-1: start with events disabled)"),2468		OPT_CALLBACK_NOOPT(0, "metric-only", &stat_config.metric_only, NULL,2469				"Only print computed metrics. No raw values", enable_metric_only),2470		OPT_BOOLEAN(0, "metric-no-group", &stat_config.metric_no_group,2471			"don't group metric events, impacts multiplexing"),2472		OPT_BOOLEAN(0, "metric-no-merge", &stat_config.metric_no_merge,2473			"don't try to share events between metrics in a group"),2474		OPT_BOOLEAN(0, "metric-no-threshold", &stat_config.metric_no_threshold,2475			"disable adding events for the metric threshold calculation"),2476		OPT_BOOLEAN(0, "topdown", &topdown_run,2477			"measure top-down statistics"),2478#ifdef HAVE_ARCH_X86_64_SUPPORT2479		OPT_BOOLEAN(0, "record-tpebs", &tpebs_recording,2480			"enable recording for tpebs when retire_latency required"),2481#endif2482		OPT_UINTEGER(0, "td-level", &stat_config.topdown_level,2483			"Set the metrics level for the top-down statistics (0: max level)"),2484		OPT_BOOLEAN(0, "smi-cost", &smi_cost,2485			"measure SMI cost"),2486		OPT_CALLBACK('M', "metrics", &evsel_list, "metric/metric group list",2487			"monitor specified metrics or metric groups (separated by ,)",2488			append_metric_groups),2489		OPT_BOOLEAN_FLAG(0, "all-kernel", &stat_config.all_kernel,2490				"Configure all used events to run in kernel space.",2491				PARSE_OPT_EXCLUSIVE),2492		OPT_BOOLEAN_FLAG(0, "all-user", &stat_config.all_user,2493				"Configure all used events to run in user space.",2494				PARSE_OPT_EXCLUSIVE),2495		OPT_BOOLEAN(0, "percore-show-thread", &stat_config.percore_show_thread,2496			"Use with 'percore' event qualifier to show the event "2497			"counts of one hardware thread by sum up total hardware "2498			"threads of same physical core"),2499		OPT_BOOLEAN(0, "summary", &stat_config.summary,2500			"print summary for interval mode"),2501		OPT_BOOLEAN(0, "no-csv-summary", &stat_config.no_csv_summary,2502			"don't print 'summary' for CSV summary output"),2503		OPT_BOOLEAN(0, "quiet", &quiet,2504			"don't print any output, messages or warnings (useful with record)"),2505		OPT_CALLBACK(0, "cputype", &evsel_list, "hybrid cpu type",2506			"Only enable events on applying cpu with this type "2507			"for hybrid platform (e.g. core or atom)",2508			parse_cputype),2509#ifdef HAVE_LIBPFM2510		OPT_CALLBACK(0, "pfm-events", &evsel_list, "event",2511			"libpfm4 event selector. use 'perf list' to list available events",2512			parse_libpfm_events_option),2513#endif2514		OPT_CALLBACK(0, "control", &stat_config, "fd:ctl-fd[,ack-fd] or fifo:ctl-fifo[,ack-fifo]",2515			"Listen on ctl-fd descriptor for command to control measurement ('enable': enable events, 'disable': disable events).\n"2516			"\t\t\t  Optionally send control command completion ('ack\\n') to ack-fd descriptor.\n"2517			"\t\t\t  Alternatively, ctl-fifo / ack-fifo will be opened and used as ctl-fd / ack-fd.",2518			parse_control_option),2519		OPT_CALLBACK_OPTARG(0, "iostat", &evsel_list, &stat_config, "default",2520				"measure I/O performance metrics provided by arch/platform",2521				iostat_parse),2522		OPT_END()2523	};2524	const char * const stat_usage[] = {2525		"perf stat [<options>] [<command>]",2526		NULL2527	};2528	int status = -EINVAL, run_idx, err;2529	const char *mode;2530	FILE *output = stderr;2531	unsigned int interval, timeout;2532	const char * const stat_subcommands[] = { "record", "report" };2533	char errbuf[BUFSIZ];2534 2535	setlocale(LC_ALL, "");2536 2537	evsel_list = evlist__new();2538	if (evsel_list == NULL)2539		return -ENOMEM;2540 2541	parse_events__shrink_config_terms();2542 2543	/* String-parsing callback-based options would segfault when negated */2544	set_option_flag(stat_options, 'e', "event", PARSE_OPT_NONEG);2545	set_option_flag(stat_options, 'M', "metrics", PARSE_OPT_NONEG);2546	set_option_flag(stat_options, 'G', "cgroup", PARSE_OPT_NONEG);2547 2548	argc = parse_options_subcommand(argc, argv, stat_options, stat_subcommands,2549					(const char **) stat_usage,2550					PARSE_OPT_STOP_AT_NON_OPTION);2551 2552	stat_config.aggr_mode = opt_aggr_mode_to_aggr_mode(&opt_mode);2553 2554	if (stat_config.csv_sep) {2555		stat_config.csv_output = true;2556		if (!strcmp(stat_config.csv_sep, "\\t"))2557			stat_config.csv_sep = "\t";2558	} else2559		stat_config.csv_sep = DEFAULT_SEPARATOR;2560 2561	if (argc && strlen(argv[0]) > 2 && strstarts("record", argv[0])) {2562		argc = __cmd_record(stat_options, &opt_mode, argc, argv);2563		if (argc < 0)2564			return -1;2565	} else if (argc && strlen(argv[0]) > 2 && strstarts("report", argv[0]))2566		return __cmd_report(argc, argv);2567 2568	interval = stat_config.interval;2569	timeout = stat_config.timeout;2570 2571	/*2572	 * For record command the -o is already taken care of.2573	 */2574	if (!STAT_RECORD && output_name && strcmp(output_name, "-"))2575		output = NULL;2576 2577	if (output_name && output_fd) {2578		fprintf(stderr, "cannot use both --output and --log-fd\n");2579		parse_options_usage(stat_usage, stat_options, "o", 1);2580		parse_options_usage(NULL, stat_options, "log-fd", 0);2581		goto out;2582	}2583 2584	if (stat_config.metric_only && stat_config.aggr_mode == AGGR_THREAD) {2585		fprintf(stderr, "--metric-only is not supported with --per-thread\n");2586		goto out;2587	}2588 2589	if (stat_config.metric_only && stat_config.run_count > 1) {2590		fprintf(stderr, "--metric-only is not supported with -r\n");2591		goto out;2592	}2593 2594	if (stat_config.walltime_run_table && stat_config.run_count <= 1) {2595		fprintf(stderr, "--table is only supported with -r\n");2596		parse_options_usage(stat_usage, stat_options, "r", 1);2597		parse_options_usage(NULL, stat_options, "table", 0);2598		goto out;2599	}2600 2601	if (output_fd < 0) {2602		fprintf(stderr, "argument to --log-fd must be a > 0\n");2603		parse_options_usage(stat_usage, stat_options, "log-fd", 0);2604		goto out;2605	}2606 2607	if (!output && !quiet) {2608		struct timespec tm;2609		mode = append_file ? "a" : "w";2610 2611		output = fopen(output_name, mode);2612		if (!output) {2613			perror("failed to create output file");2614			return -1;2615		}2616		if (!stat_config.json_output) {2617			clock_gettime(CLOCK_REALTIME, &tm);2618			fprintf(output, "# started on %s\n", ctime(&tm.tv_sec));2619		}2620	} else if (output_fd > 0) {2621		mode = append_file ? "a" : "w";2622		output = fdopen(output_fd, mode);2623		if (!output) {2624			perror("Failed opening logfd");2625			return -errno;2626		}2627	}2628 2629	if (stat_config.interval_clear && !isatty(fileno(output))) {2630		fprintf(stderr, "--interval-clear does not work with output\n");2631		parse_options_usage(stat_usage, stat_options, "o", 1);2632		parse_options_usage(NULL, stat_options, "log-fd", 0);2633		parse_options_usage(NULL, stat_options, "interval-clear", 0);2634		return -1;2635	}2636 2637	stat_config.output = output;2638 2639	/*2640	 * let the spreadsheet do the pretty-printing2641	 */2642	if (stat_config.csv_output) {2643		/* User explicitly passed -B? */2644		if (big_num_opt == 1) {2645			fprintf(stderr, "-B option not supported with -x\n");2646			parse_options_usage(stat_usage, stat_options, "B", 1);2647			parse_options_usage(NULL, stat_options, "x", 1);2648			goto out;2649		} else /* Nope, so disable big number formatting */2650			stat_config.big_num = false;2651	} else if (big_num_opt == 0) /* User passed --no-big-num */2652		stat_config.big_num = false;2653 2654	err = target__validate(&target);2655	if (err) {2656		target__strerror(&target, err, errbuf, BUFSIZ);2657		pr_warning("%s\n", errbuf);2658	}2659 2660	setup_system_wide(argc);2661 2662	/*2663	 * Display user/system times only for single2664	 * run and when there's specified tracee.2665	 */2666	if ((stat_config.run_count == 1) && target__none(&target))2667		stat_config.ru_display = true;2668 2669	if (stat_config.run_count < 0) {2670		pr_err("Run count must be a positive number\n");2671		parse_options_usage(stat_usage, stat_options, "r", 1);2672		goto out;2673	} else if (stat_config.run_count == 0) {2674		forever = true;2675		stat_config.run_count = 1;2676	}2677 2678	if (stat_config.walltime_run_table) {2679		stat_config.walltime_run = zalloc(stat_config.run_count * sizeof(stat_config.walltime_run[0]));2680		if (!stat_config.walltime_run) {2681			pr_err("failed to setup -r option");2682			goto out;2683		}2684	}2685 2686	if ((stat_config.aggr_mode == AGGR_THREAD) &&2687		!target__has_task(&target)) {2688		if (!target.system_wide || target.cpu_list) {2689			fprintf(stderr, "The --per-thread option is only "2690				"available when monitoring via -p -t -a "2691				"options or only --per-thread.\n");2692			parse_options_usage(NULL, stat_options, "p", 1);2693			parse_options_usage(NULL, stat_options, "t", 1);2694			goto out;2695		}2696	}2697 2698	/*2699	 * no_aggr, cgroup are for system-wide only2700	 * --per-thread is aggregated per thread, we dont mix it with cpu mode2701	 */2702	if (((stat_config.aggr_mode != AGGR_GLOBAL &&2703	      stat_config.aggr_mode != AGGR_THREAD) ||2704	     (nr_cgroups || stat_config.cgroup_list)) &&2705	    !target__has_cpu(&target)) {2706		fprintf(stderr, "both cgroup and no-aggregation "2707			"modes only available in system-wide mode\n");2708 2709		parse_options_usage(stat_usage, stat_options, "G", 1);2710		parse_options_usage(NULL, stat_options, "A", 1);2711		parse_options_usage(NULL, stat_options, "a", 1);2712		parse_options_usage(NULL, stat_options, "for-each-cgroup", 0);2713		goto out;2714	}2715 2716	if (stat_config.iostat_run) {2717		status = iostat_prepare(evsel_list, &stat_config);2718		if (status)2719			goto out;2720		if (iostat_mode == IOSTAT_LIST) {2721			iostat_list(evsel_list, &stat_config);2722			goto out;2723		} else if (verbose > 0)2724			iostat_list(evsel_list, &stat_config);2725		if (iostat_mode == IOSTAT_RUN && !target__has_cpu(&target))2726			target.system_wide = true;2727	}2728 2729	if ((stat_config.aggr_mode == AGGR_THREAD) && (target.system_wide))2730		target.per_thread = true;2731 2732	stat_config.system_wide = target.system_wide;2733	if (target.cpu_list) {2734		stat_config.user_requested_cpu_list = strdup(target.cpu_list);2735		if (!stat_config.user_requested_cpu_list) {2736			status = -ENOMEM;2737			goto out;2738		}2739	}2740 2741	/*2742	 * Metric parsing needs to be delayed as metrics may optimize events2743	 * knowing the target is system-wide.2744	 */2745	if (metrics) {2746		const char *pmu = parse_events_option_args.pmu_filter ?: "all";2747		int ret = metricgroup__parse_groups(evsel_list, pmu, metrics,2748						stat_config.metric_no_group,2749						stat_config.metric_no_merge,2750						stat_config.metric_no_threshold,2751						stat_config.user_requested_cpu_list,2752						stat_config.system_wide,2753						stat_config.hardware_aware_grouping,2754						&stat_config.metric_events);2755 2756		zfree(&metrics);2757		if (ret) {2758			status = ret;2759			goto out;2760		}2761	}2762 2763	if (add_default_attributes())2764		goto out;2765 2766	if (stat_config.cgroup_list) {2767		if (nr_cgroups > 0) {2768			pr_err("--cgroup and --for-each-cgroup cannot be used together\n");2769			parse_options_usage(stat_usage, stat_options, "G", 1);2770			parse_options_usage(NULL, stat_options, "for-each-cgroup", 0);2771			goto out;2772		}2773 2774		if (evlist__expand_cgroup(evsel_list, stat_config.cgroup_list,2775					  &stat_config.metric_events, true) < 0) {2776			parse_options_usage(stat_usage, stat_options,2777					    "for-each-cgroup", 0);2778			goto out;2779		}2780	}2781 2782	evlist__warn_user_requested_cpus(evsel_list, target.cpu_list);2783 2784	if (evlist__create_maps(evsel_list, &target) < 0) {2785		if (target__has_task(&target)) {2786			pr_err("Problems finding threads of monitor\n");2787			parse_options_usage(stat_usage, stat_options, "p", 1);2788			parse_options_usage(NULL, stat_options, "t", 1);2789		} else if (target__has_cpu(&target)) {2790			perror("failed to parse CPUs map");2791			parse_options_usage(stat_usage, stat_options, "C", 1);2792			parse_options_usage(NULL, stat_options, "a", 1);2793		}2794		goto out;2795	}2796 2797	evlist__check_cpu_maps(evsel_list);2798 2799	/*2800	 * Initialize thread_map with comm names,2801	 * so we could print it out on output.2802	 */2803	if (stat_config.aggr_mode == AGGR_THREAD) {2804		thread_map__read_comms(evsel_list->core.threads);2805	}2806 2807	if (stat_config.aggr_mode == AGGR_NODE)2808		cpu__setup_cpunode_map();2809 2810	if (stat_config.times && interval)2811		interval_count = true;2812	else if (stat_config.times && !interval) {2813		pr_err("interval-count option should be used together with "2814				"interval-print.\n");2815		parse_options_usage(stat_usage, stat_options, "interval-count", 0);2816		parse_options_usage(stat_usage, stat_options, "I", 1);2817		goto out;2818	}2819 2820	if (timeout && timeout < 100) {2821		if (timeout < 10) {2822			pr_err("timeout must be >= 10ms.\n");2823			parse_options_usage(stat_usage, stat_options, "timeout", 0);2824			goto out;2825		} else2826			pr_warning("timeout < 100ms. "2827				   "The overhead percentage could be high in some cases. "2828				   "Please proceed with caution.\n");2829	}2830	if (timeout && interval) {2831		pr_err("timeout option is not supported with interval-print.\n");2832		parse_options_usage(stat_usage, stat_options, "timeout", 0);2833		parse_options_usage(stat_usage, stat_options, "I", 1);2834		goto out;2835	}2836 2837	if (perf_stat_init_aggr_mode())2838		goto out;2839 2840	if (evlist__alloc_stats(&stat_config, evsel_list, interval))2841		goto out;2842 2843	/*2844	 * Set sample_type to PERF_SAMPLE_IDENTIFIER, which should be harmless2845	 * while avoiding that older tools show confusing messages.2846	 *2847	 * However for pipe sessions we need to keep it zero,2848	 * because script's perf_evsel__check_attr is triggered2849	 * by attr->sample_type != 0, and we can't run it on2850	 * stat sessions.2851	 */2852	stat_config.identifier = !(STAT_RECORD && perf_stat.data.is_pipe);2853 2854	/*2855	 * We dont want to block the signals - that would cause2856	 * child tasks to inherit that and Ctrl-C would not work.2857	 * What we want is for Ctrl-C to work in the exec()-ed2858	 * task, but being ignored by perf stat itself:2859	 */2860	atexit(sig_atexit);2861	if (!forever)2862		signal(SIGINT,  skip_signal);2863	signal(SIGCHLD, skip_signal);2864	signal(SIGALRM, skip_signal);2865	signal(SIGABRT, skip_signal);2866 2867	if (evlist__initialize_ctlfd(evsel_list, stat_config.ctl_fd, stat_config.ctl_fd_ack))2868		goto out;2869 2870	/* Enable ignoring missing threads when -p option is defined. */2871	evlist__first(evsel_list)->ignore_missing_thread = target.pid;2872	status = 0;2873	for (run_idx = 0; forever || run_idx < stat_config.run_count; run_idx++) {2874		if (stat_config.run_count != 1 && verbose > 0)2875			fprintf(output, "[ perf stat: executing run #%d ... ]\n",2876				run_idx + 1);2877 2878		if (run_idx != 0)2879			evlist__reset_prev_raw_counts(evsel_list);2880 2881		status = run_perf_stat(argc, argv, run_idx);2882		if (forever && status != -1 && !interval) {2883			print_counters(NULL, argc, argv);2884			perf_stat__reset_stats();2885		}2886	}2887 2888	if (!forever && status != -1 && (!interval || stat_config.summary)) {2889		if (stat_config.run_count > 1)2890			evlist__copy_res_stats(&stat_config, evsel_list);2891		print_counters(NULL, argc, argv);2892	}2893 2894	evlist__finalize_ctlfd(evsel_list);2895 2896	if (STAT_RECORD) {2897		/*2898		 * We synthesize the kernel mmap record just so that older tools2899		 * don't emit warnings about not being able to resolve symbols2900		 * due to /proc/sys/kernel/kptr_restrict settings and instead provide2901		 * a saner message about no samples being in the perf.data file.2902		 *2903		 * This also serves to suppress a warning about f_header.data.size == 02904		 * in header.c at the moment 'perf stat record' gets introduced, which2905		 * is not really needed once we start adding the stat specific PERF_RECORD_2906		 * records, but the need to suppress the kptr_restrict messages in older2907		 * tools remain  -acme2908		 */2909		int fd = perf_data__fd(&perf_stat.data);2910 2911		err = perf_event__synthesize_kernel_mmap((void *)&perf_stat,2912							 process_synthesized_event,2913							 &perf_stat.session->machines.host);2914		if (err) {2915			pr_warning("Couldn't synthesize the kernel mmap record, harmless, "2916				   "older tools may produce warnings about this file\n.");2917		}2918 2919		if (!interval) {2920			if (WRITE_STAT_ROUND_EVENT(walltime_nsecs_stats.max, FINAL))2921				pr_err("failed to write stat round event\n");2922		}2923 2924		if (!perf_stat.data.is_pipe) {2925			perf_stat.session->header.data_size += perf_stat.bytes_written;2926			perf_session__write_header(perf_stat.session, evsel_list, fd, true);2927		}2928 2929		evlist__close(evsel_list);2930		perf_session__delete(perf_stat.session);2931	}2932 2933	perf_stat__exit_aggr_mode();2934	evlist__free_stats(evsel_list);2935out:2936	if (stat_config.iostat_run)2937		iostat_release(evsel_list);2938 2939	zfree(&stat_config.walltime_run);2940	zfree(&stat_config.user_requested_cpu_list);2941 2942	if (smi_cost && smi_reset)2943		sysfs__write_int(FREEZE_ON_SMI_PATH, 0);2944 2945	evlist__delete(evsel_list);2946 2947	metricgroup__rblist_exit(&stat_config.metric_events);2948	evlist__close_control(stat_config.ctl_fd, stat_config.ctl_fd_ack, &stat_config.ctl_fd_close);2949 2950	return status;2951}2952