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