xref: /openbmc/linux/tools/perf/util/stat.c (revision 1fcd0394)
1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0
2a43783aeSArnaldo Carvalho de Melo #include <errno.h>
3fd20e811SArnaldo Carvalho de Melo #include <inttypes.h>
40007eceaSXiao Guangrong #include <math.h>
50007eceaSXiao Guangrong #include "stat.h"
624e34f68SJiri Olsa #include "evlist.h"
7e2f56da1SJiri Olsa #include "evsel.h"
824e34f68SJiri Olsa #include "thread_map.h"
90007eceaSXiao Guangrong 
100007eceaSXiao Guangrong void update_stats(struct stats *stats, u64 val)
110007eceaSXiao Guangrong {
120007eceaSXiao Guangrong 	double delta;
130007eceaSXiao Guangrong 
140007eceaSXiao Guangrong 	stats->n++;
150007eceaSXiao Guangrong 	delta = val - stats->mean;
160007eceaSXiao Guangrong 	stats->mean += delta / stats->n;
170007eceaSXiao Guangrong 	stats->M2 += delta*(val - stats->mean);
18ffe4f3c0SDavid Ahern 
19ffe4f3c0SDavid Ahern 	if (val > stats->max)
20ffe4f3c0SDavid Ahern 		stats->max = val;
21ffe4f3c0SDavid Ahern 
22ffe4f3c0SDavid Ahern 	if (val < stats->min)
23ffe4f3c0SDavid Ahern 		stats->min = val;
240007eceaSXiao Guangrong }
250007eceaSXiao Guangrong 
260007eceaSXiao Guangrong double avg_stats(struct stats *stats)
270007eceaSXiao Guangrong {
280007eceaSXiao Guangrong 	return stats->mean;
290007eceaSXiao Guangrong }
300007eceaSXiao Guangrong 
310007eceaSXiao Guangrong /*
320007eceaSXiao Guangrong  * http://en.wikipedia.org/wiki/Algorithms_for_calculating_variance
330007eceaSXiao Guangrong  *
340007eceaSXiao Guangrong  *       (\Sum n_i^2) - ((\Sum n_i)^2)/n
350007eceaSXiao Guangrong  * s^2 = -------------------------------
360007eceaSXiao Guangrong  *                  n - 1
370007eceaSXiao Guangrong  *
380007eceaSXiao Guangrong  * http://en.wikipedia.org/wiki/Stddev
390007eceaSXiao Guangrong  *
400007eceaSXiao Guangrong  * The std dev of the mean is related to the std dev by:
410007eceaSXiao Guangrong  *
420007eceaSXiao Guangrong  *             s
430007eceaSXiao Guangrong  * s_mean = -------
440007eceaSXiao Guangrong  *          sqrt(n)
450007eceaSXiao Guangrong  *
460007eceaSXiao Guangrong  */
470007eceaSXiao Guangrong double stddev_stats(struct stats *stats)
480007eceaSXiao Guangrong {
490007eceaSXiao Guangrong 	double variance, variance_mean;
500007eceaSXiao Guangrong 
5145528f7cSDavid Ahern 	if (stats->n < 2)
520007eceaSXiao Guangrong 		return 0.0;
530007eceaSXiao Guangrong 
540007eceaSXiao Guangrong 	variance = stats->M2 / (stats->n - 1);
550007eceaSXiao Guangrong 	variance_mean = variance / stats->n;
560007eceaSXiao Guangrong 
570007eceaSXiao Guangrong 	return sqrt(variance_mean);
580007eceaSXiao Guangrong }
590007eceaSXiao Guangrong 
600007eceaSXiao Guangrong double rel_stddev_stats(double stddev, double avg)
610007eceaSXiao Guangrong {
620007eceaSXiao Guangrong 	double pct = 0.0;
630007eceaSXiao Guangrong 
640007eceaSXiao Guangrong 	if (avg)
650007eceaSXiao Guangrong 		pct = 100.0 * stddev/avg;
660007eceaSXiao Guangrong 
670007eceaSXiao Guangrong 	return pct;
680007eceaSXiao Guangrong }
69e2f56da1SJiri Olsa 
70e2f56da1SJiri Olsa bool __perf_evsel_stat__is(struct perf_evsel *evsel,
71e2f56da1SJiri Olsa 			   enum perf_stat_evsel_id id)
72e2f56da1SJiri Olsa {
73e669e833SArnaldo Carvalho de Melo 	struct perf_stat_evsel *ps = evsel->stats;
74e2f56da1SJiri Olsa 
75e2f56da1SJiri Olsa 	return ps->id == id;
76e2f56da1SJiri Olsa }
77e2f56da1SJiri Olsa 
78e2f56da1SJiri Olsa #define ID(id, name) [PERF_STAT_EVSEL_ID__##id] = #name
79e2f56da1SJiri Olsa static const char *id_str[PERF_STAT_EVSEL_ID__MAX] = {
80e2f56da1SJiri Olsa 	ID(NONE,		x),
814c358d5cSJiri Olsa 	ID(CYCLES_IN_TX,	cpu/cycles-t/),
824c358d5cSJiri Olsa 	ID(TRANSACTION_START,	cpu/tx-start/),
834c358d5cSJiri Olsa 	ID(ELISION_START,	cpu/el-start/),
844c358d5cSJiri Olsa 	ID(CYCLES_IN_TX_CP,	cpu/cycles-ct/),
85239bd47fSAndi Kleen 	ID(TOPDOWN_TOTAL_SLOTS, topdown-total-slots),
86239bd47fSAndi Kleen 	ID(TOPDOWN_SLOTS_ISSUED, topdown-slots-issued),
87239bd47fSAndi Kleen 	ID(TOPDOWN_SLOTS_RETIRED, topdown-slots-retired),
88239bd47fSAndi Kleen 	ID(TOPDOWN_FETCH_BUBBLES, topdown-fetch-bubbles),
89239bd47fSAndi Kleen 	ID(TOPDOWN_RECOVERY_BUBBLES, topdown-recovery-bubbles),
90daefd0bcSKan Liang 	ID(SMI_NUM, msr/smi/),
91daefd0bcSKan Liang 	ID(APERF, msr/aperf/),
92e2f56da1SJiri Olsa };
93e2f56da1SJiri Olsa #undef ID
94e2f56da1SJiri Olsa 
95e2f56da1SJiri Olsa void perf_stat_evsel_id_init(struct perf_evsel *evsel)
96e2f56da1SJiri Olsa {
97e669e833SArnaldo Carvalho de Melo 	struct perf_stat_evsel *ps = evsel->stats;
98e2f56da1SJiri Olsa 	int i;
99e2f56da1SJiri Olsa 
100e2f56da1SJiri Olsa 	/* ps->id is 0 hence PERF_STAT_EVSEL_ID__NONE by default */
101e2f56da1SJiri Olsa 
102e2f56da1SJiri Olsa 	for (i = 0; i < PERF_STAT_EVSEL_ID__MAX; i++) {
103e2f56da1SJiri Olsa 		if (!strcmp(perf_evsel__name(evsel), id_str[i])) {
104e2f56da1SJiri Olsa 			ps->id = i;
105e2f56da1SJiri Olsa 			break;
106e2f56da1SJiri Olsa 		}
107e2f56da1SJiri Olsa 	}
108e2f56da1SJiri Olsa }
109a9a3a4d9SJiri Olsa 
11086a2cf31SJiri Olsa static void perf_evsel__reset_stat_priv(struct perf_evsel *evsel)
1119689edfaSJiri Olsa {
1129689edfaSJiri Olsa 	int i;
113e669e833SArnaldo Carvalho de Melo 	struct perf_stat_evsel *ps = evsel->stats;
1149689edfaSJiri Olsa 
1159689edfaSJiri Olsa 	for (i = 0; i < 3; i++)
1169689edfaSJiri Olsa 		init_stats(&ps->res_stats[i]);
1179689edfaSJiri Olsa 
1189689edfaSJiri Olsa 	perf_stat_evsel_id_init(evsel);
1199689edfaSJiri Olsa }
1209689edfaSJiri Olsa 
12186a2cf31SJiri Olsa static int perf_evsel__alloc_stat_priv(struct perf_evsel *evsel)
1229689edfaSJiri Olsa {
123e669e833SArnaldo Carvalho de Melo 	evsel->stats = zalloc(sizeof(struct perf_stat_evsel));
124e669e833SArnaldo Carvalho de Melo 	if (evsel->stats == NULL)
1259689edfaSJiri Olsa 		return -ENOMEM;
1269689edfaSJiri Olsa 	perf_evsel__reset_stat_priv(evsel);
1279689edfaSJiri Olsa 	return 0;
1289689edfaSJiri Olsa }
1299689edfaSJiri Olsa 
13086a2cf31SJiri Olsa static void perf_evsel__free_stat_priv(struct perf_evsel *evsel)
1319689edfaSJiri Olsa {
132e669e833SArnaldo Carvalho de Melo 	struct perf_stat_evsel *ps = evsel->stats;
133f7794d52SJiri Olsa 
134f7794d52SJiri Olsa 	if (ps)
135f7794d52SJiri Olsa 		free(ps->group_data);
136e669e833SArnaldo Carvalho de Melo 	zfree(&evsel->stats);
1379689edfaSJiri Olsa }
138a939512dSJiri Olsa 
13986a2cf31SJiri Olsa static int perf_evsel__alloc_prev_raw_counts(struct perf_evsel *evsel,
140a939512dSJiri Olsa 					     int ncpus, int nthreads)
141a939512dSJiri Olsa {
142a939512dSJiri Olsa 	struct perf_counts *counts;
143a939512dSJiri Olsa 
144a939512dSJiri Olsa 	counts = perf_counts__new(ncpus, nthreads);
145a939512dSJiri Olsa 	if (counts)
146a939512dSJiri Olsa 		evsel->prev_raw_counts = counts;
147a939512dSJiri Olsa 
148a939512dSJiri Olsa 	return counts ? 0 : -ENOMEM;
149a939512dSJiri Olsa }
150a939512dSJiri Olsa 
15186a2cf31SJiri Olsa static void perf_evsel__free_prev_raw_counts(struct perf_evsel *evsel)
152a939512dSJiri Olsa {
153a939512dSJiri Olsa 	perf_counts__delete(evsel->prev_raw_counts);
154a939512dSJiri Olsa 	evsel->prev_raw_counts = NULL;
155a939512dSJiri Olsa }
15624e34f68SJiri Olsa 
15786a2cf31SJiri Olsa static int perf_evsel__alloc_stats(struct perf_evsel *evsel, bool alloc_raw)
15824e34f68SJiri Olsa {
15924e34f68SJiri Olsa 	int ncpus = perf_evsel__nr_cpus(evsel);
160a7d0a102SJiri Olsa 	int nthreads = thread_map__nr(evsel->threads);
16124e34f68SJiri Olsa 
16224e34f68SJiri Olsa 	if (perf_evsel__alloc_stat_priv(evsel) < 0 ||
16324e34f68SJiri Olsa 	    perf_evsel__alloc_counts(evsel, ncpus, nthreads) < 0 ||
16424e34f68SJiri Olsa 	    (alloc_raw && perf_evsel__alloc_prev_raw_counts(evsel, ncpus, nthreads) < 0))
165a7d0a102SJiri Olsa 		return -ENOMEM;
166a7d0a102SJiri Olsa 
167a7d0a102SJiri Olsa 	return 0;
168a7d0a102SJiri Olsa }
169a7d0a102SJiri Olsa 
170a7d0a102SJiri Olsa int perf_evlist__alloc_stats(struct perf_evlist *evlist, bool alloc_raw)
171a7d0a102SJiri Olsa {
172a7d0a102SJiri Olsa 	struct perf_evsel *evsel;
173a7d0a102SJiri Olsa 
174e5cadb93SArnaldo Carvalho de Melo 	evlist__for_each_entry(evlist, evsel) {
175a7d0a102SJiri Olsa 		if (perf_evsel__alloc_stats(evsel, alloc_raw))
17624e34f68SJiri Olsa 			goto out_free;
17724e34f68SJiri Olsa 	}
17824e34f68SJiri Olsa 
17924e34f68SJiri Olsa 	return 0;
18024e34f68SJiri Olsa 
18124e34f68SJiri Olsa out_free:
18224e34f68SJiri Olsa 	perf_evlist__free_stats(evlist);
18324e34f68SJiri Olsa 	return -1;
18424e34f68SJiri Olsa }
18524e34f68SJiri Olsa 
18624e34f68SJiri Olsa void perf_evlist__free_stats(struct perf_evlist *evlist)
18724e34f68SJiri Olsa {
18824e34f68SJiri Olsa 	struct perf_evsel *evsel;
18924e34f68SJiri Olsa 
190e5cadb93SArnaldo Carvalho de Melo 	evlist__for_each_entry(evlist, evsel) {
19124e34f68SJiri Olsa 		perf_evsel__free_stat_priv(evsel);
19224e34f68SJiri Olsa 		perf_evsel__free_counts(evsel);
19324e34f68SJiri Olsa 		perf_evsel__free_prev_raw_counts(evsel);
19424e34f68SJiri Olsa 	}
19524e34f68SJiri Olsa }
19624e34f68SJiri Olsa 
19724e34f68SJiri Olsa void perf_evlist__reset_stats(struct perf_evlist *evlist)
19824e34f68SJiri Olsa {
19924e34f68SJiri Olsa 	struct perf_evsel *evsel;
20024e34f68SJiri Olsa 
201e5cadb93SArnaldo Carvalho de Melo 	evlist__for_each_entry(evlist, evsel) {
20224e34f68SJiri Olsa 		perf_evsel__reset_stat_priv(evsel);
20324e34f68SJiri Olsa 		perf_evsel__reset_counts(evsel);
20424e34f68SJiri Olsa 	}
20524e34f68SJiri Olsa }
206f80010ebSJiri Olsa 
207f80010ebSJiri Olsa static void zero_per_pkg(struct perf_evsel *counter)
208f80010ebSJiri Olsa {
209f80010ebSJiri Olsa 	if (counter->per_pkg_mask)
210f80010ebSJiri Olsa 		memset(counter->per_pkg_mask, 0, MAX_NR_CPUS);
211f80010ebSJiri Olsa }
212f80010ebSJiri Olsa 
21302d8dabcSStephane Eranian static int check_per_pkg(struct perf_evsel *counter,
21402d8dabcSStephane Eranian 			 struct perf_counts_values *vals, int cpu, bool *skip)
215f80010ebSJiri Olsa {
216f80010ebSJiri Olsa 	unsigned long *mask = counter->per_pkg_mask;
217f80010ebSJiri Olsa 	struct cpu_map *cpus = perf_evsel__cpus(counter);
218f80010ebSJiri Olsa 	int s;
219f80010ebSJiri Olsa 
220f80010ebSJiri Olsa 	*skip = false;
221f80010ebSJiri Olsa 
222f80010ebSJiri Olsa 	if (!counter->per_pkg)
223f80010ebSJiri Olsa 		return 0;
224f80010ebSJiri Olsa 
225f80010ebSJiri Olsa 	if (cpu_map__empty(cpus))
226f80010ebSJiri Olsa 		return 0;
227f80010ebSJiri Olsa 
228f80010ebSJiri Olsa 	if (!mask) {
229f80010ebSJiri Olsa 		mask = zalloc(MAX_NR_CPUS);
230f80010ebSJiri Olsa 		if (!mask)
231f80010ebSJiri Olsa 			return -ENOMEM;
232f80010ebSJiri Olsa 
233f80010ebSJiri Olsa 		counter->per_pkg_mask = mask;
234f80010ebSJiri Olsa 	}
235f80010ebSJiri Olsa 
23602d8dabcSStephane Eranian 	/*
23702d8dabcSStephane Eranian 	 * we do not consider an event that has not run as a good
23802d8dabcSStephane Eranian 	 * instance to mark a package as used (skip=1). Otherwise
23902d8dabcSStephane Eranian 	 * we may run into a situation where the first CPU in a package
24002d8dabcSStephane Eranian 	 * is not running anything, yet the second is, and this function
24102d8dabcSStephane Eranian 	 * would mark the package as used after the first CPU and would
24202d8dabcSStephane Eranian 	 * not read the values from the second CPU.
24302d8dabcSStephane Eranian 	 */
24402d8dabcSStephane Eranian 	if (!(vals->run && vals->ena))
24502d8dabcSStephane Eranian 		return 0;
24602d8dabcSStephane Eranian 
2471fe7a300SJiri Olsa 	s = cpu_map__get_socket(cpus, cpu, NULL);
248f80010ebSJiri Olsa 	if (s < 0)
249f80010ebSJiri Olsa 		return -1;
250f80010ebSJiri Olsa 
251f80010ebSJiri Olsa 	*skip = test_and_set_bit(s, mask) == 1;
252f80010ebSJiri Olsa 	return 0;
253f80010ebSJiri Olsa }
254f80010ebSJiri Olsa 
255f80010ebSJiri Olsa static int
256f80010ebSJiri Olsa process_counter_values(struct perf_stat_config *config, struct perf_evsel *evsel,
257f80010ebSJiri Olsa 		       int cpu, int thread,
258f80010ebSJiri Olsa 		       struct perf_counts_values *count)
259f80010ebSJiri Olsa {
260f80010ebSJiri Olsa 	struct perf_counts_values *aggr = &evsel->counts->aggr;
261f80010ebSJiri Olsa 	static struct perf_counts_values zero;
262f80010ebSJiri Olsa 	bool skip = false;
263f80010ebSJiri Olsa 
26402d8dabcSStephane Eranian 	if (check_per_pkg(evsel, count, cpu, &skip)) {
265f80010ebSJiri Olsa 		pr_err("failed to read per-pkg counter\n");
266f80010ebSJiri Olsa 		return -1;
267f80010ebSJiri Olsa 	}
268f80010ebSJiri Olsa 
269f80010ebSJiri Olsa 	if (skip)
270f80010ebSJiri Olsa 		count = &zero;
271f80010ebSJiri Olsa 
272f80010ebSJiri Olsa 	switch (config->aggr_mode) {
273f80010ebSJiri Olsa 	case AGGR_THREAD:
274f80010ebSJiri Olsa 	case AGGR_CORE:
275f80010ebSJiri Olsa 	case AGGR_SOCKET:
276f80010ebSJiri Olsa 	case AGGR_NONE:
277f80010ebSJiri Olsa 		if (!evsel->snapshot)
278f80010ebSJiri Olsa 			perf_evsel__compute_deltas(evsel, cpu, thread, count);
279f80010ebSJiri Olsa 		perf_counts_values__scale(count, config->scale, NULL);
280f80010ebSJiri Olsa 		if (config->aggr_mode == AGGR_NONE)
2811fcd0394SJin Yao 			perf_stat__update_shadow_stats(evsel, count->val, cpu,
2821fcd0394SJin Yao 						       &rt_stat);
283021b462aSJiri Olsa 		if (config->aggr_mode == AGGR_THREAD)
2841fcd0394SJin Yao 			perf_stat__update_shadow_stats(evsel, count->val, 0,
2851fcd0394SJin Yao 						       &rt_stat);
286f80010ebSJiri Olsa 		break;
287f80010ebSJiri Olsa 	case AGGR_GLOBAL:
288f80010ebSJiri Olsa 		aggr->val += count->val;
289f80010ebSJiri Olsa 		if (config->scale) {
290f80010ebSJiri Olsa 			aggr->ena += count->ena;
291f80010ebSJiri Olsa 			aggr->run += count->run;
292f80010ebSJiri Olsa 		}
293208df99eSJiri Olsa 	case AGGR_UNSET:
294f80010ebSJiri Olsa 	default:
295f80010ebSJiri Olsa 		break;
296f80010ebSJiri Olsa 	}
297f80010ebSJiri Olsa 
298f80010ebSJiri Olsa 	return 0;
299f80010ebSJiri Olsa }
300f80010ebSJiri Olsa 
301f80010ebSJiri Olsa static int process_counter_maps(struct perf_stat_config *config,
302f80010ebSJiri Olsa 				struct perf_evsel *counter)
303f80010ebSJiri Olsa {
304f80010ebSJiri Olsa 	int nthreads = thread_map__nr(counter->threads);
305f80010ebSJiri Olsa 	int ncpus = perf_evsel__nr_cpus(counter);
306f80010ebSJiri Olsa 	int cpu, thread;
307f80010ebSJiri Olsa 
308f80010ebSJiri Olsa 	if (counter->system_wide)
309f80010ebSJiri Olsa 		nthreads = 1;
310f80010ebSJiri Olsa 
311f80010ebSJiri Olsa 	for (thread = 0; thread < nthreads; thread++) {
312f80010ebSJiri Olsa 		for (cpu = 0; cpu < ncpus; cpu++) {
313f80010ebSJiri Olsa 			if (process_counter_values(config, counter, cpu, thread,
314f80010ebSJiri Olsa 						   perf_counts(counter->counts, cpu, thread)))
315f80010ebSJiri Olsa 				return -1;
316f80010ebSJiri Olsa 		}
317f80010ebSJiri Olsa 	}
318f80010ebSJiri Olsa 
319f80010ebSJiri Olsa 	return 0;
320f80010ebSJiri Olsa }
321f80010ebSJiri Olsa 
322f80010ebSJiri Olsa int perf_stat_process_counter(struct perf_stat_config *config,
323f80010ebSJiri Olsa 			      struct perf_evsel *counter)
324f80010ebSJiri Olsa {
325f80010ebSJiri Olsa 	struct perf_counts_values *aggr = &counter->counts->aggr;
326e669e833SArnaldo Carvalho de Melo 	struct perf_stat_evsel *ps = counter->stats;
327f80010ebSJiri Olsa 	u64 *count = counter->counts->aggr.values;
328f80010ebSJiri Olsa 	int i, ret;
329f80010ebSJiri Olsa 
330f80010ebSJiri Olsa 	aggr->val = aggr->ena = aggr->run = 0;
331f80010ebSJiri Olsa 
33251fd2df1SJiri Olsa 	/*
33351fd2df1SJiri Olsa 	 * We calculate counter's data every interval,
33451fd2df1SJiri Olsa 	 * and the display code shows ps->res_stats
33551fd2df1SJiri Olsa 	 * avg value. We need to zero the stats for
33651fd2df1SJiri Olsa 	 * interval mode, otherwise overall avg running
33751fd2df1SJiri Olsa 	 * averages will be shown for each interval.
33851fd2df1SJiri Olsa 	 */
33951fd2df1SJiri Olsa 	if (config->interval)
34051fd2df1SJiri Olsa 		init_stats(ps->res_stats);
34151fd2df1SJiri Olsa 
342f80010ebSJiri Olsa 	if (counter->per_pkg)
343f80010ebSJiri Olsa 		zero_per_pkg(counter);
344f80010ebSJiri Olsa 
345f80010ebSJiri Olsa 	ret = process_counter_maps(config, counter);
346f80010ebSJiri Olsa 	if (ret)
347f80010ebSJiri Olsa 		return ret;
348f80010ebSJiri Olsa 
349f80010ebSJiri Olsa 	if (config->aggr_mode != AGGR_GLOBAL)
350f80010ebSJiri Olsa 		return 0;
351f80010ebSJiri Olsa 
352f80010ebSJiri Olsa 	if (!counter->snapshot)
353f80010ebSJiri Olsa 		perf_evsel__compute_deltas(counter, -1, -1, aggr);
354f80010ebSJiri Olsa 	perf_counts_values__scale(aggr, config->scale, &counter->counts->scaled);
355f80010ebSJiri Olsa 
356f80010ebSJiri Olsa 	for (i = 0; i < 3; i++)
357f80010ebSJiri Olsa 		update_stats(&ps->res_stats[i], count[i]);
358f80010ebSJiri Olsa 
359bb963e16SNamhyung Kim 	if (verbose > 0) {
360f80010ebSJiri Olsa 		fprintf(config->output, "%s: %" PRIu64 " %" PRIu64 " %" PRIu64 "\n",
361f80010ebSJiri Olsa 			perf_evsel__name(counter), count[0], count[1], count[2]);
362f80010ebSJiri Olsa 	}
363f80010ebSJiri Olsa 
364f80010ebSJiri Olsa 	/*
365f80010ebSJiri Olsa 	 * Save the full runtime - to allow normalization during printout:
366f80010ebSJiri Olsa 	 */
3671fcd0394SJin Yao 	perf_stat__update_shadow_stats(counter, *count, 0, &rt_stat);
368f80010ebSJiri Olsa 
369f80010ebSJiri Olsa 	return 0;
370f80010ebSJiri Olsa }
3710ea0e355SJiri Olsa 
3720ea0e355SJiri Olsa int perf_event__process_stat_event(struct perf_tool *tool __maybe_unused,
3730ea0e355SJiri Olsa 				   union perf_event *event,
3740ea0e355SJiri Olsa 				   struct perf_session *session)
3750ea0e355SJiri Olsa {
3760ea0e355SJiri Olsa 	struct perf_counts_values count;
3770ea0e355SJiri Olsa 	struct stat_event *st = &event->stat;
3780ea0e355SJiri Olsa 	struct perf_evsel *counter;
3790ea0e355SJiri Olsa 
3800ea0e355SJiri Olsa 	count.val = st->val;
3810ea0e355SJiri Olsa 	count.ena = st->ena;
3820ea0e355SJiri Olsa 	count.run = st->run;
3830ea0e355SJiri Olsa 
3840ea0e355SJiri Olsa 	counter = perf_evlist__id2evsel(session->evlist, st->id);
3850ea0e355SJiri Olsa 	if (!counter) {
3860ea0e355SJiri Olsa 		pr_err("Failed to resolve counter for stat event.\n");
3870ea0e355SJiri Olsa 		return -EINVAL;
3880ea0e355SJiri Olsa 	}
3890ea0e355SJiri Olsa 
3900ea0e355SJiri Olsa 	*perf_counts(counter->counts, st->cpu, st->thread) = count;
3910ea0e355SJiri Olsa 	counter->supported = true;
3920ea0e355SJiri Olsa 	return 0;
3930ea0e355SJiri Olsa }
394e08a4564SJiri Olsa 
395e08a4564SJiri Olsa size_t perf_event__fprintf_stat(union perf_event *event, FILE *fp)
396e08a4564SJiri Olsa {
397e08a4564SJiri Olsa 	struct stat_event *st = (struct stat_event *) event;
398e08a4564SJiri Olsa 	size_t ret;
399e08a4564SJiri Olsa 
400e08a4564SJiri Olsa 	ret  = fprintf(fp, "\n... id %" PRIu64 ", cpu %d, thread %d\n",
401e08a4564SJiri Olsa 		       st->id, st->cpu, st->thread);
402e08a4564SJiri Olsa 	ret += fprintf(fp, "... value %" PRIu64 ", enabled %" PRIu64 ", running %" PRIu64 "\n",
403e08a4564SJiri Olsa 		       st->val, st->ena, st->run);
404e08a4564SJiri Olsa 
405e08a4564SJiri Olsa 	return ret;
406e08a4564SJiri Olsa }
407e08a4564SJiri Olsa 
408e08a4564SJiri Olsa size_t perf_event__fprintf_stat_round(union perf_event *event, FILE *fp)
409e08a4564SJiri Olsa {
410e08a4564SJiri Olsa 	struct stat_round_event *rd = (struct stat_round_event *)event;
411e08a4564SJiri Olsa 	size_t ret;
412e08a4564SJiri Olsa 
413e08a4564SJiri Olsa 	ret = fprintf(fp, "\n... time %" PRIu64 ", type %s\n", rd->time,
414e08a4564SJiri Olsa 		      rd->type == PERF_STAT_ROUND_TYPE__FINAL ? "FINAL" : "INTERVAL");
415e08a4564SJiri Olsa 
416e08a4564SJiri Olsa 	return ret;
417e08a4564SJiri Olsa }
418e08a4564SJiri Olsa 
419e08a4564SJiri Olsa size_t perf_event__fprintf_stat_config(union perf_event *event, FILE *fp)
420e08a4564SJiri Olsa {
421e08a4564SJiri Olsa 	struct perf_stat_config sc;
422e08a4564SJiri Olsa 	size_t ret;
423e08a4564SJiri Olsa 
424e08a4564SJiri Olsa 	perf_event__read_stat_config(&sc, &event->stat_config);
425e08a4564SJiri Olsa 
426e08a4564SJiri Olsa 	ret  = fprintf(fp, "\n");
427e08a4564SJiri Olsa 	ret += fprintf(fp, "... aggr_mode %d\n", sc.aggr_mode);
428e08a4564SJiri Olsa 	ret += fprintf(fp, "... scale     %d\n", sc.scale);
429e08a4564SJiri Olsa 	ret += fprintf(fp, "... interval  %u\n", sc.interval);
430e08a4564SJiri Olsa 
431e08a4564SJiri Olsa 	return ret;
432e08a4564SJiri Olsa }
433