xref: /kernel/linux/linux-5.10/tools/perf/util/stat.c (revision 8c2ecf20)
18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
28c2ecf20Sopenharmony_ci#include <errno.h>
38c2ecf20Sopenharmony_ci#include <inttypes.h>
48c2ecf20Sopenharmony_ci#include <math.h>
58c2ecf20Sopenharmony_ci#include <string.h>
68c2ecf20Sopenharmony_ci#include "counts.h"
78c2ecf20Sopenharmony_ci#include "cpumap.h"
88c2ecf20Sopenharmony_ci#include "debug.h"
98c2ecf20Sopenharmony_ci#include "header.h"
108c2ecf20Sopenharmony_ci#include "stat.h"
118c2ecf20Sopenharmony_ci#include "session.h"
128c2ecf20Sopenharmony_ci#include "target.h"
138c2ecf20Sopenharmony_ci#include "evlist.h"
148c2ecf20Sopenharmony_ci#include "evsel.h"
158c2ecf20Sopenharmony_ci#include "thread_map.h"
168c2ecf20Sopenharmony_ci#include <linux/zalloc.h>
178c2ecf20Sopenharmony_ci
188c2ecf20Sopenharmony_civoid update_stats(struct stats *stats, u64 val)
198c2ecf20Sopenharmony_ci{
208c2ecf20Sopenharmony_ci	double delta;
218c2ecf20Sopenharmony_ci
228c2ecf20Sopenharmony_ci	stats->n++;
238c2ecf20Sopenharmony_ci	delta = val - stats->mean;
248c2ecf20Sopenharmony_ci	stats->mean += delta / stats->n;
258c2ecf20Sopenharmony_ci	stats->M2 += delta*(val - stats->mean);
268c2ecf20Sopenharmony_ci
278c2ecf20Sopenharmony_ci	if (val > stats->max)
288c2ecf20Sopenharmony_ci		stats->max = val;
298c2ecf20Sopenharmony_ci
308c2ecf20Sopenharmony_ci	if (val < stats->min)
318c2ecf20Sopenharmony_ci		stats->min = val;
328c2ecf20Sopenharmony_ci}
338c2ecf20Sopenharmony_ci
348c2ecf20Sopenharmony_cidouble avg_stats(struct stats *stats)
358c2ecf20Sopenharmony_ci{
368c2ecf20Sopenharmony_ci	return stats->mean;
378c2ecf20Sopenharmony_ci}
388c2ecf20Sopenharmony_ci
398c2ecf20Sopenharmony_ci/*
408c2ecf20Sopenharmony_ci * http://en.wikipedia.org/wiki/Algorithms_for_calculating_variance
418c2ecf20Sopenharmony_ci *
428c2ecf20Sopenharmony_ci *       (\Sum n_i^2) - ((\Sum n_i)^2)/n
438c2ecf20Sopenharmony_ci * s^2 = -------------------------------
448c2ecf20Sopenharmony_ci *                  n - 1
458c2ecf20Sopenharmony_ci *
468c2ecf20Sopenharmony_ci * http://en.wikipedia.org/wiki/Stddev
478c2ecf20Sopenharmony_ci *
488c2ecf20Sopenharmony_ci * The std dev of the mean is related to the std dev by:
498c2ecf20Sopenharmony_ci *
508c2ecf20Sopenharmony_ci *             s
518c2ecf20Sopenharmony_ci * s_mean = -------
528c2ecf20Sopenharmony_ci *          sqrt(n)
538c2ecf20Sopenharmony_ci *
548c2ecf20Sopenharmony_ci */
558c2ecf20Sopenharmony_cidouble stddev_stats(struct stats *stats)
568c2ecf20Sopenharmony_ci{
578c2ecf20Sopenharmony_ci	double variance, variance_mean;
588c2ecf20Sopenharmony_ci
598c2ecf20Sopenharmony_ci	if (stats->n < 2)
608c2ecf20Sopenharmony_ci		return 0.0;
618c2ecf20Sopenharmony_ci
628c2ecf20Sopenharmony_ci	variance = stats->M2 / (stats->n - 1);
638c2ecf20Sopenharmony_ci	variance_mean = variance / stats->n;
648c2ecf20Sopenharmony_ci
658c2ecf20Sopenharmony_ci	return sqrt(variance_mean);
668c2ecf20Sopenharmony_ci}
678c2ecf20Sopenharmony_ci
688c2ecf20Sopenharmony_cidouble rel_stddev_stats(double stddev, double avg)
698c2ecf20Sopenharmony_ci{
708c2ecf20Sopenharmony_ci	double pct = 0.0;
718c2ecf20Sopenharmony_ci
728c2ecf20Sopenharmony_ci	if (avg)
738c2ecf20Sopenharmony_ci		pct = 100.0 * stddev/avg;
748c2ecf20Sopenharmony_ci
758c2ecf20Sopenharmony_ci	return pct;
768c2ecf20Sopenharmony_ci}
778c2ecf20Sopenharmony_ci
788c2ecf20Sopenharmony_cibool __perf_evsel_stat__is(struct evsel *evsel,
798c2ecf20Sopenharmony_ci			   enum perf_stat_evsel_id id)
808c2ecf20Sopenharmony_ci{
818c2ecf20Sopenharmony_ci	struct perf_stat_evsel *ps = evsel->stats;
828c2ecf20Sopenharmony_ci
838c2ecf20Sopenharmony_ci	return ps->id == id;
848c2ecf20Sopenharmony_ci}
858c2ecf20Sopenharmony_ci
868c2ecf20Sopenharmony_ci#define ID(id, name) [PERF_STAT_EVSEL_ID__##id] = #name
878c2ecf20Sopenharmony_cistatic const char *id_str[PERF_STAT_EVSEL_ID__MAX] = {
888c2ecf20Sopenharmony_ci	ID(NONE,		x),
898c2ecf20Sopenharmony_ci	ID(CYCLES_IN_TX,	cpu/cycles-t/),
908c2ecf20Sopenharmony_ci	ID(TRANSACTION_START,	cpu/tx-start/),
918c2ecf20Sopenharmony_ci	ID(ELISION_START,	cpu/el-start/),
928c2ecf20Sopenharmony_ci	ID(CYCLES_IN_TX_CP,	cpu/cycles-ct/),
938c2ecf20Sopenharmony_ci	ID(TOPDOWN_TOTAL_SLOTS, topdown-total-slots),
948c2ecf20Sopenharmony_ci	ID(TOPDOWN_SLOTS_ISSUED, topdown-slots-issued),
958c2ecf20Sopenharmony_ci	ID(TOPDOWN_SLOTS_RETIRED, topdown-slots-retired),
968c2ecf20Sopenharmony_ci	ID(TOPDOWN_FETCH_BUBBLES, topdown-fetch-bubbles),
978c2ecf20Sopenharmony_ci	ID(TOPDOWN_RECOVERY_BUBBLES, topdown-recovery-bubbles),
988c2ecf20Sopenharmony_ci	ID(TOPDOWN_RETIRING, topdown-retiring),
998c2ecf20Sopenharmony_ci	ID(TOPDOWN_BAD_SPEC, topdown-bad-spec),
1008c2ecf20Sopenharmony_ci	ID(TOPDOWN_FE_BOUND, topdown-fe-bound),
1018c2ecf20Sopenharmony_ci	ID(TOPDOWN_BE_BOUND, topdown-be-bound),
1028c2ecf20Sopenharmony_ci	ID(SMI_NUM, msr/smi/),
1038c2ecf20Sopenharmony_ci	ID(APERF, msr/aperf/),
1048c2ecf20Sopenharmony_ci};
1058c2ecf20Sopenharmony_ci#undef ID
1068c2ecf20Sopenharmony_ci
1078c2ecf20Sopenharmony_cistatic void perf_stat_evsel_id_init(struct evsel *evsel)
1088c2ecf20Sopenharmony_ci{
1098c2ecf20Sopenharmony_ci	struct perf_stat_evsel *ps = evsel->stats;
1108c2ecf20Sopenharmony_ci	int i;
1118c2ecf20Sopenharmony_ci
1128c2ecf20Sopenharmony_ci	/* ps->id is 0 hence PERF_STAT_EVSEL_ID__NONE by default */
1138c2ecf20Sopenharmony_ci
1148c2ecf20Sopenharmony_ci	for (i = 0; i < PERF_STAT_EVSEL_ID__MAX; i++) {
1158c2ecf20Sopenharmony_ci		if (!strcmp(evsel__name(evsel), id_str[i])) {
1168c2ecf20Sopenharmony_ci			ps->id = i;
1178c2ecf20Sopenharmony_ci			break;
1188c2ecf20Sopenharmony_ci		}
1198c2ecf20Sopenharmony_ci	}
1208c2ecf20Sopenharmony_ci}
1218c2ecf20Sopenharmony_ci
1228c2ecf20Sopenharmony_cistatic void evsel__reset_stat_priv(struct evsel *evsel)
1238c2ecf20Sopenharmony_ci{
1248c2ecf20Sopenharmony_ci	int i;
1258c2ecf20Sopenharmony_ci	struct perf_stat_evsel *ps = evsel->stats;
1268c2ecf20Sopenharmony_ci
1278c2ecf20Sopenharmony_ci	for (i = 0; i < 3; i++)
1288c2ecf20Sopenharmony_ci		init_stats(&ps->res_stats[i]);
1298c2ecf20Sopenharmony_ci
1308c2ecf20Sopenharmony_ci	perf_stat_evsel_id_init(evsel);
1318c2ecf20Sopenharmony_ci}
1328c2ecf20Sopenharmony_ci
1338c2ecf20Sopenharmony_cistatic int evsel__alloc_stat_priv(struct evsel *evsel)
1348c2ecf20Sopenharmony_ci{
1358c2ecf20Sopenharmony_ci	evsel->stats = zalloc(sizeof(struct perf_stat_evsel));
1368c2ecf20Sopenharmony_ci	if (evsel->stats == NULL)
1378c2ecf20Sopenharmony_ci		return -ENOMEM;
1388c2ecf20Sopenharmony_ci	evsel__reset_stat_priv(evsel);
1398c2ecf20Sopenharmony_ci	return 0;
1408c2ecf20Sopenharmony_ci}
1418c2ecf20Sopenharmony_ci
1428c2ecf20Sopenharmony_cistatic void evsel__free_stat_priv(struct evsel *evsel)
1438c2ecf20Sopenharmony_ci{
1448c2ecf20Sopenharmony_ci	struct perf_stat_evsel *ps = evsel->stats;
1458c2ecf20Sopenharmony_ci
1468c2ecf20Sopenharmony_ci	if (ps)
1478c2ecf20Sopenharmony_ci		zfree(&ps->group_data);
1488c2ecf20Sopenharmony_ci	zfree(&evsel->stats);
1498c2ecf20Sopenharmony_ci}
1508c2ecf20Sopenharmony_ci
1518c2ecf20Sopenharmony_cistatic int evsel__alloc_prev_raw_counts(struct evsel *evsel, int ncpus, int nthreads)
1528c2ecf20Sopenharmony_ci{
1538c2ecf20Sopenharmony_ci	struct perf_counts *counts;
1548c2ecf20Sopenharmony_ci
1558c2ecf20Sopenharmony_ci	counts = perf_counts__new(ncpus, nthreads);
1568c2ecf20Sopenharmony_ci	if (counts)
1578c2ecf20Sopenharmony_ci		evsel->prev_raw_counts = counts;
1588c2ecf20Sopenharmony_ci
1598c2ecf20Sopenharmony_ci	return counts ? 0 : -ENOMEM;
1608c2ecf20Sopenharmony_ci}
1618c2ecf20Sopenharmony_ci
1628c2ecf20Sopenharmony_cistatic void evsel__free_prev_raw_counts(struct evsel *evsel)
1638c2ecf20Sopenharmony_ci{
1648c2ecf20Sopenharmony_ci	perf_counts__delete(evsel->prev_raw_counts);
1658c2ecf20Sopenharmony_ci	evsel->prev_raw_counts = NULL;
1668c2ecf20Sopenharmony_ci}
1678c2ecf20Sopenharmony_ci
1688c2ecf20Sopenharmony_cistatic void evsel__reset_prev_raw_counts(struct evsel *evsel)
1698c2ecf20Sopenharmony_ci{
1708c2ecf20Sopenharmony_ci	if (evsel->prev_raw_counts)
1718c2ecf20Sopenharmony_ci		perf_counts__reset(evsel->prev_raw_counts);
1728c2ecf20Sopenharmony_ci}
1738c2ecf20Sopenharmony_ci
1748c2ecf20Sopenharmony_cistatic int evsel__alloc_stats(struct evsel *evsel, bool alloc_raw)
1758c2ecf20Sopenharmony_ci{
1768c2ecf20Sopenharmony_ci	int ncpus = evsel__nr_cpus(evsel);
1778c2ecf20Sopenharmony_ci	int nthreads = perf_thread_map__nr(evsel->core.threads);
1788c2ecf20Sopenharmony_ci
1798c2ecf20Sopenharmony_ci	if (evsel__alloc_stat_priv(evsel) < 0 ||
1808c2ecf20Sopenharmony_ci	    evsel__alloc_counts(evsel, ncpus, nthreads) < 0 ||
1818c2ecf20Sopenharmony_ci	    (alloc_raw && evsel__alloc_prev_raw_counts(evsel, ncpus, nthreads) < 0))
1828c2ecf20Sopenharmony_ci		return -ENOMEM;
1838c2ecf20Sopenharmony_ci
1848c2ecf20Sopenharmony_ci	return 0;
1858c2ecf20Sopenharmony_ci}
1868c2ecf20Sopenharmony_ci
1878c2ecf20Sopenharmony_ciint perf_evlist__alloc_stats(struct evlist *evlist, bool alloc_raw)
1888c2ecf20Sopenharmony_ci{
1898c2ecf20Sopenharmony_ci	struct evsel *evsel;
1908c2ecf20Sopenharmony_ci
1918c2ecf20Sopenharmony_ci	evlist__for_each_entry(evlist, evsel) {
1928c2ecf20Sopenharmony_ci		if (evsel__alloc_stats(evsel, alloc_raw))
1938c2ecf20Sopenharmony_ci			goto out_free;
1948c2ecf20Sopenharmony_ci	}
1958c2ecf20Sopenharmony_ci
1968c2ecf20Sopenharmony_ci	return 0;
1978c2ecf20Sopenharmony_ci
1988c2ecf20Sopenharmony_ciout_free:
1998c2ecf20Sopenharmony_ci	perf_evlist__free_stats(evlist);
2008c2ecf20Sopenharmony_ci	return -1;
2018c2ecf20Sopenharmony_ci}
2028c2ecf20Sopenharmony_ci
2038c2ecf20Sopenharmony_civoid perf_evlist__free_stats(struct evlist *evlist)
2048c2ecf20Sopenharmony_ci{
2058c2ecf20Sopenharmony_ci	struct evsel *evsel;
2068c2ecf20Sopenharmony_ci
2078c2ecf20Sopenharmony_ci	evlist__for_each_entry(evlist, evsel) {
2088c2ecf20Sopenharmony_ci		evsel__free_stat_priv(evsel);
2098c2ecf20Sopenharmony_ci		evsel__free_counts(evsel);
2108c2ecf20Sopenharmony_ci		evsel__free_prev_raw_counts(evsel);
2118c2ecf20Sopenharmony_ci	}
2128c2ecf20Sopenharmony_ci}
2138c2ecf20Sopenharmony_ci
2148c2ecf20Sopenharmony_civoid perf_evlist__reset_stats(struct evlist *evlist)
2158c2ecf20Sopenharmony_ci{
2168c2ecf20Sopenharmony_ci	struct evsel *evsel;
2178c2ecf20Sopenharmony_ci
2188c2ecf20Sopenharmony_ci	evlist__for_each_entry(evlist, evsel) {
2198c2ecf20Sopenharmony_ci		evsel__reset_stat_priv(evsel);
2208c2ecf20Sopenharmony_ci		evsel__reset_counts(evsel);
2218c2ecf20Sopenharmony_ci	}
2228c2ecf20Sopenharmony_ci}
2238c2ecf20Sopenharmony_ci
2248c2ecf20Sopenharmony_civoid perf_evlist__reset_prev_raw_counts(struct evlist *evlist)
2258c2ecf20Sopenharmony_ci{
2268c2ecf20Sopenharmony_ci	struct evsel *evsel;
2278c2ecf20Sopenharmony_ci
2288c2ecf20Sopenharmony_ci	evlist__for_each_entry(evlist, evsel)
2298c2ecf20Sopenharmony_ci		evsel__reset_prev_raw_counts(evsel);
2308c2ecf20Sopenharmony_ci}
2318c2ecf20Sopenharmony_ci
2328c2ecf20Sopenharmony_cistatic void perf_evsel__copy_prev_raw_counts(struct evsel *evsel)
2338c2ecf20Sopenharmony_ci{
2348c2ecf20Sopenharmony_ci	int ncpus = evsel__nr_cpus(evsel);
2358c2ecf20Sopenharmony_ci	int nthreads = perf_thread_map__nr(evsel->core.threads);
2368c2ecf20Sopenharmony_ci
2378c2ecf20Sopenharmony_ci	for (int thread = 0; thread < nthreads; thread++) {
2388c2ecf20Sopenharmony_ci		for (int cpu = 0; cpu < ncpus; cpu++) {
2398c2ecf20Sopenharmony_ci			*perf_counts(evsel->counts, cpu, thread) =
2408c2ecf20Sopenharmony_ci				*perf_counts(evsel->prev_raw_counts, cpu,
2418c2ecf20Sopenharmony_ci					     thread);
2428c2ecf20Sopenharmony_ci		}
2438c2ecf20Sopenharmony_ci	}
2448c2ecf20Sopenharmony_ci
2458c2ecf20Sopenharmony_ci	evsel->counts->aggr = evsel->prev_raw_counts->aggr;
2468c2ecf20Sopenharmony_ci}
2478c2ecf20Sopenharmony_ci
2488c2ecf20Sopenharmony_civoid perf_evlist__copy_prev_raw_counts(struct evlist *evlist)
2498c2ecf20Sopenharmony_ci{
2508c2ecf20Sopenharmony_ci	struct evsel *evsel;
2518c2ecf20Sopenharmony_ci
2528c2ecf20Sopenharmony_ci	evlist__for_each_entry(evlist, evsel)
2538c2ecf20Sopenharmony_ci		perf_evsel__copy_prev_raw_counts(evsel);
2548c2ecf20Sopenharmony_ci}
2558c2ecf20Sopenharmony_ci
2568c2ecf20Sopenharmony_civoid perf_evlist__save_aggr_prev_raw_counts(struct evlist *evlist)
2578c2ecf20Sopenharmony_ci{
2588c2ecf20Sopenharmony_ci	struct evsel *evsel;
2598c2ecf20Sopenharmony_ci
2608c2ecf20Sopenharmony_ci	/*
2618c2ecf20Sopenharmony_ci	 * To collect the overall statistics for interval mode,
2628c2ecf20Sopenharmony_ci	 * we copy the counts from evsel->prev_raw_counts to
2638c2ecf20Sopenharmony_ci	 * evsel->counts. The perf_stat_process_counter creates
2648c2ecf20Sopenharmony_ci	 * aggr values from per cpu values, but the per cpu values
2658c2ecf20Sopenharmony_ci	 * are 0 for AGGR_GLOBAL. So we use a trick that saves the
2668c2ecf20Sopenharmony_ci	 * previous aggr value to the first member of perf_counts,
2678c2ecf20Sopenharmony_ci	 * then aggr calculation in process_counter_values can work
2688c2ecf20Sopenharmony_ci	 * correctly.
2698c2ecf20Sopenharmony_ci	 */
2708c2ecf20Sopenharmony_ci	evlist__for_each_entry(evlist, evsel) {
2718c2ecf20Sopenharmony_ci		*perf_counts(evsel->prev_raw_counts, 0, 0) =
2728c2ecf20Sopenharmony_ci			evsel->prev_raw_counts->aggr;
2738c2ecf20Sopenharmony_ci	}
2748c2ecf20Sopenharmony_ci}
2758c2ecf20Sopenharmony_ci
2768c2ecf20Sopenharmony_cistatic void zero_per_pkg(struct evsel *counter)
2778c2ecf20Sopenharmony_ci{
2788c2ecf20Sopenharmony_ci	if (counter->per_pkg_mask)
2798c2ecf20Sopenharmony_ci		memset(counter->per_pkg_mask, 0, cpu__max_cpu());
2808c2ecf20Sopenharmony_ci}
2818c2ecf20Sopenharmony_ci
2828c2ecf20Sopenharmony_cistatic int check_per_pkg(struct evsel *counter,
2838c2ecf20Sopenharmony_ci			 struct perf_counts_values *vals, int cpu, bool *skip)
2848c2ecf20Sopenharmony_ci{
2858c2ecf20Sopenharmony_ci	unsigned long *mask = counter->per_pkg_mask;
2868c2ecf20Sopenharmony_ci	struct perf_cpu_map *cpus = evsel__cpus(counter);
2878c2ecf20Sopenharmony_ci	int s;
2888c2ecf20Sopenharmony_ci
2898c2ecf20Sopenharmony_ci	*skip = false;
2908c2ecf20Sopenharmony_ci
2918c2ecf20Sopenharmony_ci	if (!counter->per_pkg)
2928c2ecf20Sopenharmony_ci		return 0;
2938c2ecf20Sopenharmony_ci
2948c2ecf20Sopenharmony_ci	if (perf_cpu_map__empty(cpus))
2958c2ecf20Sopenharmony_ci		return 0;
2968c2ecf20Sopenharmony_ci
2978c2ecf20Sopenharmony_ci	if (!mask) {
2988c2ecf20Sopenharmony_ci		mask = zalloc(cpu__max_cpu());
2998c2ecf20Sopenharmony_ci		if (!mask)
3008c2ecf20Sopenharmony_ci			return -ENOMEM;
3018c2ecf20Sopenharmony_ci
3028c2ecf20Sopenharmony_ci		counter->per_pkg_mask = mask;
3038c2ecf20Sopenharmony_ci	}
3048c2ecf20Sopenharmony_ci
3058c2ecf20Sopenharmony_ci	/*
3068c2ecf20Sopenharmony_ci	 * we do not consider an event that has not run as a good
3078c2ecf20Sopenharmony_ci	 * instance to mark a package as used (skip=1). Otherwise
3088c2ecf20Sopenharmony_ci	 * we may run into a situation where the first CPU in a package
3098c2ecf20Sopenharmony_ci	 * is not running anything, yet the second is, and this function
3108c2ecf20Sopenharmony_ci	 * would mark the package as used after the first CPU and would
3118c2ecf20Sopenharmony_ci	 * not read the values from the second CPU.
3128c2ecf20Sopenharmony_ci	 */
3138c2ecf20Sopenharmony_ci	if (!(vals->run && vals->ena))
3148c2ecf20Sopenharmony_ci		return 0;
3158c2ecf20Sopenharmony_ci
3168c2ecf20Sopenharmony_ci	s = cpu_map__get_socket(cpus, cpu, NULL);
3178c2ecf20Sopenharmony_ci	if (s < 0)
3188c2ecf20Sopenharmony_ci		return -1;
3198c2ecf20Sopenharmony_ci
3208c2ecf20Sopenharmony_ci	*skip = test_and_set_bit(s, mask) == 1;
3218c2ecf20Sopenharmony_ci	return 0;
3228c2ecf20Sopenharmony_ci}
3238c2ecf20Sopenharmony_ci
3248c2ecf20Sopenharmony_cistatic int
3258c2ecf20Sopenharmony_ciprocess_counter_values(struct perf_stat_config *config, struct evsel *evsel,
3268c2ecf20Sopenharmony_ci		       int cpu, int thread,
3278c2ecf20Sopenharmony_ci		       struct perf_counts_values *count)
3288c2ecf20Sopenharmony_ci{
3298c2ecf20Sopenharmony_ci	struct perf_counts_values *aggr = &evsel->counts->aggr;
3308c2ecf20Sopenharmony_ci	static struct perf_counts_values zero;
3318c2ecf20Sopenharmony_ci	bool skip = false;
3328c2ecf20Sopenharmony_ci
3338c2ecf20Sopenharmony_ci	if (check_per_pkg(evsel, count, cpu, &skip)) {
3348c2ecf20Sopenharmony_ci		pr_err("failed to read per-pkg counter\n");
3358c2ecf20Sopenharmony_ci		return -1;
3368c2ecf20Sopenharmony_ci	}
3378c2ecf20Sopenharmony_ci
3388c2ecf20Sopenharmony_ci	if (skip)
3398c2ecf20Sopenharmony_ci		count = &zero;
3408c2ecf20Sopenharmony_ci
3418c2ecf20Sopenharmony_ci	switch (config->aggr_mode) {
3428c2ecf20Sopenharmony_ci	case AGGR_THREAD:
3438c2ecf20Sopenharmony_ci	case AGGR_CORE:
3448c2ecf20Sopenharmony_ci	case AGGR_DIE:
3458c2ecf20Sopenharmony_ci	case AGGR_SOCKET:
3468c2ecf20Sopenharmony_ci	case AGGR_NODE:
3478c2ecf20Sopenharmony_ci	case AGGR_NONE:
3488c2ecf20Sopenharmony_ci		if (!evsel->snapshot)
3498c2ecf20Sopenharmony_ci			evsel__compute_deltas(evsel, cpu, thread, count);
3508c2ecf20Sopenharmony_ci		perf_counts_values__scale(count, config->scale, NULL);
3518c2ecf20Sopenharmony_ci		if ((config->aggr_mode == AGGR_NONE) && (!evsel->percore)) {
3528c2ecf20Sopenharmony_ci			perf_stat__update_shadow_stats(evsel, count->val,
3538c2ecf20Sopenharmony_ci						       cpu, &rt_stat);
3548c2ecf20Sopenharmony_ci		}
3558c2ecf20Sopenharmony_ci
3568c2ecf20Sopenharmony_ci		if (config->aggr_mode == AGGR_THREAD) {
3578c2ecf20Sopenharmony_ci			if (config->stats)
3588c2ecf20Sopenharmony_ci				perf_stat__update_shadow_stats(evsel,
3598c2ecf20Sopenharmony_ci					count->val, 0, &config->stats[thread]);
3608c2ecf20Sopenharmony_ci			else
3618c2ecf20Sopenharmony_ci				perf_stat__update_shadow_stats(evsel,
3628c2ecf20Sopenharmony_ci					count->val, 0, &rt_stat);
3638c2ecf20Sopenharmony_ci		}
3648c2ecf20Sopenharmony_ci		break;
3658c2ecf20Sopenharmony_ci	case AGGR_GLOBAL:
3668c2ecf20Sopenharmony_ci		aggr->val += count->val;
3678c2ecf20Sopenharmony_ci		aggr->ena += count->ena;
3688c2ecf20Sopenharmony_ci		aggr->run += count->run;
3698c2ecf20Sopenharmony_ci	case AGGR_UNSET:
3708c2ecf20Sopenharmony_ci	default:
3718c2ecf20Sopenharmony_ci		break;
3728c2ecf20Sopenharmony_ci	}
3738c2ecf20Sopenharmony_ci
3748c2ecf20Sopenharmony_ci	return 0;
3758c2ecf20Sopenharmony_ci}
3768c2ecf20Sopenharmony_ci
3778c2ecf20Sopenharmony_cistatic int process_counter_maps(struct perf_stat_config *config,
3788c2ecf20Sopenharmony_ci				struct evsel *counter)
3798c2ecf20Sopenharmony_ci{
3808c2ecf20Sopenharmony_ci	int nthreads = perf_thread_map__nr(counter->core.threads);
3818c2ecf20Sopenharmony_ci	int ncpus = evsel__nr_cpus(counter);
3828c2ecf20Sopenharmony_ci	int cpu, thread;
3838c2ecf20Sopenharmony_ci
3848c2ecf20Sopenharmony_ci	if (counter->core.system_wide)
3858c2ecf20Sopenharmony_ci		nthreads = 1;
3868c2ecf20Sopenharmony_ci
3878c2ecf20Sopenharmony_ci	for (thread = 0; thread < nthreads; thread++) {
3888c2ecf20Sopenharmony_ci		for (cpu = 0; cpu < ncpus; cpu++) {
3898c2ecf20Sopenharmony_ci			if (process_counter_values(config, counter, cpu, thread,
3908c2ecf20Sopenharmony_ci						   perf_counts(counter->counts, cpu, thread)))
3918c2ecf20Sopenharmony_ci				return -1;
3928c2ecf20Sopenharmony_ci		}
3938c2ecf20Sopenharmony_ci	}
3948c2ecf20Sopenharmony_ci
3958c2ecf20Sopenharmony_ci	return 0;
3968c2ecf20Sopenharmony_ci}
3978c2ecf20Sopenharmony_ci
3988c2ecf20Sopenharmony_ciint perf_stat_process_counter(struct perf_stat_config *config,
3998c2ecf20Sopenharmony_ci			      struct evsel *counter)
4008c2ecf20Sopenharmony_ci{
4018c2ecf20Sopenharmony_ci	struct perf_counts_values *aggr = &counter->counts->aggr;
4028c2ecf20Sopenharmony_ci	struct perf_stat_evsel *ps = counter->stats;
4038c2ecf20Sopenharmony_ci	u64 *count = counter->counts->aggr.values;
4048c2ecf20Sopenharmony_ci	int i, ret;
4058c2ecf20Sopenharmony_ci
4068c2ecf20Sopenharmony_ci	aggr->val = aggr->ena = aggr->run = 0;
4078c2ecf20Sopenharmony_ci
4088c2ecf20Sopenharmony_ci	/*
4098c2ecf20Sopenharmony_ci	 * We calculate counter's data every interval,
4108c2ecf20Sopenharmony_ci	 * and the display code shows ps->res_stats
4118c2ecf20Sopenharmony_ci	 * avg value. We need to zero the stats for
4128c2ecf20Sopenharmony_ci	 * interval mode, otherwise overall avg running
4138c2ecf20Sopenharmony_ci	 * averages will be shown for each interval.
4148c2ecf20Sopenharmony_ci	 */
4158c2ecf20Sopenharmony_ci	if (config->interval || config->summary) {
4168c2ecf20Sopenharmony_ci		for (i = 0; i < 3; i++)
4178c2ecf20Sopenharmony_ci			init_stats(&ps->res_stats[i]);
4188c2ecf20Sopenharmony_ci	}
4198c2ecf20Sopenharmony_ci
4208c2ecf20Sopenharmony_ci	if (counter->per_pkg)
4218c2ecf20Sopenharmony_ci		zero_per_pkg(counter);
4228c2ecf20Sopenharmony_ci
4238c2ecf20Sopenharmony_ci	ret = process_counter_maps(config, counter);
4248c2ecf20Sopenharmony_ci	if (ret)
4258c2ecf20Sopenharmony_ci		return ret;
4268c2ecf20Sopenharmony_ci
4278c2ecf20Sopenharmony_ci	if (config->aggr_mode != AGGR_GLOBAL)
4288c2ecf20Sopenharmony_ci		return 0;
4298c2ecf20Sopenharmony_ci
4308c2ecf20Sopenharmony_ci	if (!counter->snapshot)
4318c2ecf20Sopenharmony_ci		evsel__compute_deltas(counter, -1, -1, aggr);
4328c2ecf20Sopenharmony_ci	perf_counts_values__scale(aggr, config->scale, &counter->counts->scaled);
4338c2ecf20Sopenharmony_ci
4348c2ecf20Sopenharmony_ci	for (i = 0; i < 3; i++)
4358c2ecf20Sopenharmony_ci		update_stats(&ps->res_stats[i], count[i]);
4368c2ecf20Sopenharmony_ci
4378c2ecf20Sopenharmony_ci	if (verbose > 0) {
4388c2ecf20Sopenharmony_ci		fprintf(config->output, "%s: %" PRIu64 " %" PRIu64 " %" PRIu64 "\n",
4398c2ecf20Sopenharmony_ci			evsel__name(counter), count[0], count[1], count[2]);
4408c2ecf20Sopenharmony_ci	}
4418c2ecf20Sopenharmony_ci
4428c2ecf20Sopenharmony_ci	/*
4438c2ecf20Sopenharmony_ci	 * Save the full runtime - to allow normalization during printout:
4448c2ecf20Sopenharmony_ci	 */
4458c2ecf20Sopenharmony_ci	perf_stat__update_shadow_stats(counter, *count, 0, &rt_stat);
4468c2ecf20Sopenharmony_ci
4478c2ecf20Sopenharmony_ci	return 0;
4488c2ecf20Sopenharmony_ci}
4498c2ecf20Sopenharmony_ci
4508c2ecf20Sopenharmony_ciint perf_event__process_stat_event(struct perf_session *session,
4518c2ecf20Sopenharmony_ci				   union perf_event *event)
4528c2ecf20Sopenharmony_ci{
4538c2ecf20Sopenharmony_ci	struct perf_counts_values count;
4548c2ecf20Sopenharmony_ci	struct perf_record_stat *st = &event->stat;
4558c2ecf20Sopenharmony_ci	struct evsel *counter;
4568c2ecf20Sopenharmony_ci
4578c2ecf20Sopenharmony_ci	count.val = st->val;
4588c2ecf20Sopenharmony_ci	count.ena = st->ena;
4598c2ecf20Sopenharmony_ci	count.run = st->run;
4608c2ecf20Sopenharmony_ci
4618c2ecf20Sopenharmony_ci	counter = perf_evlist__id2evsel(session->evlist, st->id);
4628c2ecf20Sopenharmony_ci	if (!counter) {
4638c2ecf20Sopenharmony_ci		pr_err("Failed to resolve counter for stat event.\n");
4648c2ecf20Sopenharmony_ci		return -EINVAL;
4658c2ecf20Sopenharmony_ci	}
4668c2ecf20Sopenharmony_ci
4678c2ecf20Sopenharmony_ci	*perf_counts(counter->counts, st->cpu, st->thread) = count;
4688c2ecf20Sopenharmony_ci	counter->supported = true;
4698c2ecf20Sopenharmony_ci	return 0;
4708c2ecf20Sopenharmony_ci}
4718c2ecf20Sopenharmony_ci
4728c2ecf20Sopenharmony_cisize_t perf_event__fprintf_stat(union perf_event *event, FILE *fp)
4738c2ecf20Sopenharmony_ci{
4748c2ecf20Sopenharmony_ci	struct perf_record_stat *st = (struct perf_record_stat *)event;
4758c2ecf20Sopenharmony_ci	size_t ret;
4768c2ecf20Sopenharmony_ci
4778c2ecf20Sopenharmony_ci	ret  = fprintf(fp, "\n... id %" PRI_lu64 ", cpu %d, thread %d\n",
4788c2ecf20Sopenharmony_ci		       st->id, st->cpu, st->thread);
4798c2ecf20Sopenharmony_ci	ret += fprintf(fp, "... value %" PRI_lu64 ", enabled %" PRI_lu64 ", running %" PRI_lu64 "\n",
4808c2ecf20Sopenharmony_ci		       st->val, st->ena, st->run);
4818c2ecf20Sopenharmony_ci
4828c2ecf20Sopenharmony_ci	return ret;
4838c2ecf20Sopenharmony_ci}
4848c2ecf20Sopenharmony_ci
4858c2ecf20Sopenharmony_cisize_t perf_event__fprintf_stat_round(union perf_event *event, FILE *fp)
4868c2ecf20Sopenharmony_ci{
4878c2ecf20Sopenharmony_ci	struct perf_record_stat_round *rd = (struct perf_record_stat_round *)event;
4888c2ecf20Sopenharmony_ci	size_t ret;
4898c2ecf20Sopenharmony_ci
4908c2ecf20Sopenharmony_ci	ret = fprintf(fp, "\n... time %" PRI_lu64 ", type %s\n", rd->time,
4918c2ecf20Sopenharmony_ci		      rd->type == PERF_STAT_ROUND_TYPE__FINAL ? "FINAL" : "INTERVAL");
4928c2ecf20Sopenharmony_ci
4938c2ecf20Sopenharmony_ci	return ret;
4948c2ecf20Sopenharmony_ci}
4958c2ecf20Sopenharmony_ci
4968c2ecf20Sopenharmony_cisize_t perf_event__fprintf_stat_config(union perf_event *event, FILE *fp)
4978c2ecf20Sopenharmony_ci{
4988c2ecf20Sopenharmony_ci	struct perf_stat_config sc;
4998c2ecf20Sopenharmony_ci	size_t ret;
5008c2ecf20Sopenharmony_ci
5018c2ecf20Sopenharmony_ci	perf_event__read_stat_config(&sc, &event->stat_config);
5028c2ecf20Sopenharmony_ci
5038c2ecf20Sopenharmony_ci	ret  = fprintf(fp, "\n");
5048c2ecf20Sopenharmony_ci	ret += fprintf(fp, "... aggr_mode %d\n", sc.aggr_mode);
5058c2ecf20Sopenharmony_ci	ret += fprintf(fp, "... scale     %d\n", sc.scale);
5068c2ecf20Sopenharmony_ci	ret += fprintf(fp, "... interval  %u\n", sc.interval);
5078c2ecf20Sopenharmony_ci
5088c2ecf20Sopenharmony_ci	return ret;
5098c2ecf20Sopenharmony_ci}
5108c2ecf20Sopenharmony_ci
5118c2ecf20Sopenharmony_ciint create_perf_stat_counter(struct evsel *evsel,
5128c2ecf20Sopenharmony_ci			     struct perf_stat_config *config,
5138c2ecf20Sopenharmony_ci			     struct target *target,
5148c2ecf20Sopenharmony_ci			     int cpu)
5158c2ecf20Sopenharmony_ci{
5168c2ecf20Sopenharmony_ci	struct perf_event_attr *attr = &evsel->core.attr;
5178c2ecf20Sopenharmony_ci	struct evsel *leader = evsel->leader;
5188c2ecf20Sopenharmony_ci
5198c2ecf20Sopenharmony_ci	attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED |
5208c2ecf20Sopenharmony_ci			    PERF_FORMAT_TOTAL_TIME_RUNNING;
5218c2ecf20Sopenharmony_ci
5228c2ecf20Sopenharmony_ci	/*
5238c2ecf20Sopenharmony_ci	 * The event is part of non trivial group, let's enable
5248c2ecf20Sopenharmony_ci	 * the group read (for leader) and ID retrieval for all
5258c2ecf20Sopenharmony_ci	 * members.
5268c2ecf20Sopenharmony_ci	 */
5278c2ecf20Sopenharmony_ci	if (leader->core.nr_members > 1)
5288c2ecf20Sopenharmony_ci		attr->read_format |= PERF_FORMAT_ID|PERF_FORMAT_GROUP;
5298c2ecf20Sopenharmony_ci
5308c2ecf20Sopenharmony_ci	attr->inherit = !config->no_inherit;
5318c2ecf20Sopenharmony_ci
5328c2ecf20Sopenharmony_ci	/*
5338c2ecf20Sopenharmony_ci	 * Some events get initialized with sample_(period/type) set,
5348c2ecf20Sopenharmony_ci	 * like tracepoints. Clear it up for counting.
5358c2ecf20Sopenharmony_ci	 */
5368c2ecf20Sopenharmony_ci	attr->sample_period = 0;
5378c2ecf20Sopenharmony_ci
5388c2ecf20Sopenharmony_ci	if (config->identifier)
5398c2ecf20Sopenharmony_ci		attr->sample_type = PERF_SAMPLE_IDENTIFIER;
5408c2ecf20Sopenharmony_ci
5418c2ecf20Sopenharmony_ci	if (config->all_user) {
5428c2ecf20Sopenharmony_ci		attr->exclude_kernel = 1;
5438c2ecf20Sopenharmony_ci		attr->exclude_user   = 0;
5448c2ecf20Sopenharmony_ci	}
5458c2ecf20Sopenharmony_ci
5468c2ecf20Sopenharmony_ci	if (config->all_kernel) {
5478c2ecf20Sopenharmony_ci		attr->exclude_kernel = 0;
5488c2ecf20Sopenharmony_ci		attr->exclude_user   = 1;
5498c2ecf20Sopenharmony_ci	}
5508c2ecf20Sopenharmony_ci
5518c2ecf20Sopenharmony_ci	/*
5528c2ecf20Sopenharmony_ci	 * Disabling all counters initially, they will be enabled
5538c2ecf20Sopenharmony_ci	 * either manually by us or by kernel via enable_on_exec
5548c2ecf20Sopenharmony_ci	 * set later.
5558c2ecf20Sopenharmony_ci	 */
5568c2ecf20Sopenharmony_ci	if (evsel__is_group_leader(evsel)) {
5578c2ecf20Sopenharmony_ci		attr->disabled = 1;
5588c2ecf20Sopenharmony_ci
5598c2ecf20Sopenharmony_ci		/*
5608c2ecf20Sopenharmony_ci		 * In case of initial_delay we enable tracee
5618c2ecf20Sopenharmony_ci		 * events manually.
5628c2ecf20Sopenharmony_ci		 */
5638c2ecf20Sopenharmony_ci		if (target__none(target) && !config->initial_delay)
5648c2ecf20Sopenharmony_ci			attr->enable_on_exec = 1;
5658c2ecf20Sopenharmony_ci	}
5668c2ecf20Sopenharmony_ci
5678c2ecf20Sopenharmony_ci	if (target__has_cpu(target) && !target__has_per_thread(target))
5688c2ecf20Sopenharmony_ci		return evsel__open_per_cpu(evsel, evsel__cpus(evsel), cpu);
5698c2ecf20Sopenharmony_ci
5708c2ecf20Sopenharmony_ci	return evsel__open_per_thread(evsel, evsel->core.threads);
5718c2ecf20Sopenharmony_ci}
572