18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Copyright (C) 2011, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com>
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Parts came from builtin-{top,stat,record}.c, see those files for further
68c2ecf20Sopenharmony_ci * copyright notes.
78c2ecf20Sopenharmony_ci */
88c2ecf20Sopenharmony_ci
98c2ecf20Sopenharmony_ci#include <byteswap.h>
108c2ecf20Sopenharmony_ci#include <errno.h>
118c2ecf20Sopenharmony_ci#include <inttypes.h>
128c2ecf20Sopenharmony_ci#include <linux/bitops.h>
138c2ecf20Sopenharmony_ci#include <api/fs/fs.h>
148c2ecf20Sopenharmony_ci#include <api/fs/tracing_path.h>
158c2ecf20Sopenharmony_ci#include <traceevent/event-parse.h>
168c2ecf20Sopenharmony_ci#include <linux/hw_breakpoint.h>
178c2ecf20Sopenharmony_ci#include <linux/perf_event.h>
188c2ecf20Sopenharmony_ci#include <linux/compiler.h>
198c2ecf20Sopenharmony_ci#include <linux/err.h>
208c2ecf20Sopenharmony_ci#include <linux/zalloc.h>
218c2ecf20Sopenharmony_ci#include <sys/ioctl.h>
228c2ecf20Sopenharmony_ci#include <sys/resource.h>
238c2ecf20Sopenharmony_ci#include <sys/types.h>
248c2ecf20Sopenharmony_ci#include <dirent.h>
258c2ecf20Sopenharmony_ci#include <stdlib.h>
268c2ecf20Sopenharmony_ci#include <perf/evsel.h>
278c2ecf20Sopenharmony_ci#include "asm/bug.h"
288c2ecf20Sopenharmony_ci#include "callchain.h"
298c2ecf20Sopenharmony_ci#include "cgroup.h"
308c2ecf20Sopenharmony_ci#include "counts.h"
318c2ecf20Sopenharmony_ci#include "event.h"
328c2ecf20Sopenharmony_ci#include "evsel.h"
338c2ecf20Sopenharmony_ci#include "util/env.h"
348c2ecf20Sopenharmony_ci#include "util/evsel_config.h"
358c2ecf20Sopenharmony_ci#include "util/evsel_fprintf.h"
368c2ecf20Sopenharmony_ci#include "evlist.h"
378c2ecf20Sopenharmony_ci#include <perf/cpumap.h>
388c2ecf20Sopenharmony_ci#include "thread_map.h"
398c2ecf20Sopenharmony_ci#include "target.h"
408c2ecf20Sopenharmony_ci#include "perf_regs.h"
418c2ecf20Sopenharmony_ci#include "record.h"
428c2ecf20Sopenharmony_ci#include "debug.h"
438c2ecf20Sopenharmony_ci#include "trace-event.h"
448c2ecf20Sopenharmony_ci#include "stat.h"
458c2ecf20Sopenharmony_ci#include "string2.h"
468c2ecf20Sopenharmony_ci#include "memswap.h"
478c2ecf20Sopenharmony_ci#include "util.h"
488c2ecf20Sopenharmony_ci#include "../perf-sys.h"
498c2ecf20Sopenharmony_ci#include "util/parse-branch-options.h"
508c2ecf20Sopenharmony_ci#include <internal/xyarray.h>
518c2ecf20Sopenharmony_ci#include <internal/lib.h>
528c2ecf20Sopenharmony_ci
538c2ecf20Sopenharmony_ci#include <linux/ctype.h>
548c2ecf20Sopenharmony_ci
558c2ecf20Sopenharmony_cistruct perf_missing_features perf_missing_features;
568c2ecf20Sopenharmony_ci
578c2ecf20Sopenharmony_cistatic clockid_t clockid;
588c2ecf20Sopenharmony_ci
598c2ecf20Sopenharmony_cistatic int evsel__no_extra_init(struct evsel *evsel __maybe_unused)
608c2ecf20Sopenharmony_ci{
618c2ecf20Sopenharmony_ci	return 0;
628c2ecf20Sopenharmony_ci}
638c2ecf20Sopenharmony_ci
648c2ecf20Sopenharmony_civoid __weak test_attr__ready(void) { }
658c2ecf20Sopenharmony_ci
668c2ecf20Sopenharmony_cistatic void evsel__no_extra_fini(struct evsel *evsel __maybe_unused)
678c2ecf20Sopenharmony_ci{
688c2ecf20Sopenharmony_ci}
698c2ecf20Sopenharmony_ci
708c2ecf20Sopenharmony_cistatic struct {
718c2ecf20Sopenharmony_ci	size_t	size;
728c2ecf20Sopenharmony_ci	int	(*init)(struct evsel *evsel);
738c2ecf20Sopenharmony_ci	void	(*fini)(struct evsel *evsel);
748c2ecf20Sopenharmony_ci} perf_evsel__object = {
758c2ecf20Sopenharmony_ci	.size = sizeof(struct evsel),
768c2ecf20Sopenharmony_ci	.init = evsel__no_extra_init,
778c2ecf20Sopenharmony_ci	.fini = evsel__no_extra_fini,
788c2ecf20Sopenharmony_ci};
798c2ecf20Sopenharmony_ci
808c2ecf20Sopenharmony_ciint evsel__object_config(size_t object_size, int (*init)(struct evsel *evsel),
818c2ecf20Sopenharmony_ci			 void (*fini)(struct evsel *evsel))
828c2ecf20Sopenharmony_ci{
838c2ecf20Sopenharmony_ci
848c2ecf20Sopenharmony_ci	if (object_size == 0)
858c2ecf20Sopenharmony_ci		goto set_methods;
868c2ecf20Sopenharmony_ci
878c2ecf20Sopenharmony_ci	if (perf_evsel__object.size > object_size)
888c2ecf20Sopenharmony_ci		return -EINVAL;
898c2ecf20Sopenharmony_ci
908c2ecf20Sopenharmony_ci	perf_evsel__object.size = object_size;
918c2ecf20Sopenharmony_ci
928c2ecf20Sopenharmony_ciset_methods:
938c2ecf20Sopenharmony_ci	if (init != NULL)
948c2ecf20Sopenharmony_ci		perf_evsel__object.init = init;
958c2ecf20Sopenharmony_ci
968c2ecf20Sopenharmony_ci	if (fini != NULL)
978c2ecf20Sopenharmony_ci		perf_evsel__object.fini = fini;
988c2ecf20Sopenharmony_ci
998c2ecf20Sopenharmony_ci	return 0;
1008c2ecf20Sopenharmony_ci}
1018c2ecf20Sopenharmony_ci
1028c2ecf20Sopenharmony_ci#define FD(e, x, y) (*(int *)xyarray__entry(e->core.fd, x, y))
1038c2ecf20Sopenharmony_ci
1048c2ecf20Sopenharmony_ciint __evsel__sample_size(u64 sample_type)
1058c2ecf20Sopenharmony_ci{
1068c2ecf20Sopenharmony_ci	u64 mask = sample_type & PERF_SAMPLE_MASK;
1078c2ecf20Sopenharmony_ci	int size = 0;
1088c2ecf20Sopenharmony_ci	int i;
1098c2ecf20Sopenharmony_ci
1108c2ecf20Sopenharmony_ci	for (i = 0; i < 64; i++) {
1118c2ecf20Sopenharmony_ci		if (mask & (1ULL << i))
1128c2ecf20Sopenharmony_ci			size++;
1138c2ecf20Sopenharmony_ci	}
1148c2ecf20Sopenharmony_ci
1158c2ecf20Sopenharmony_ci	size *= sizeof(u64);
1168c2ecf20Sopenharmony_ci
1178c2ecf20Sopenharmony_ci	return size;
1188c2ecf20Sopenharmony_ci}
1198c2ecf20Sopenharmony_ci
1208c2ecf20Sopenharmony_ci/**
1218c2ecf20Sopenharmony_ci * __perf_evsel__calc_id_pos - calculate id_pos.
1228c2ecf20Sopenharmony_ci * @sample_type: sample type
1238c2ecf20Sopenharmony_ci *
1248c2ecf20Sopenharmony_ci * This function returns the position of the event id (PERF_SAMPLE_ID or
1258c2ecf20Sopenharmony_ci * PERF_SAMPLE_IDENTIFIER) in a sample event i.e. in the array of struct
1268c2ecf20Sopenharmony_ci * perf_record_sample.
1278c2ecf20Sopenharmony_ci */
1288c2ecf20Sopenharmony_cistatic int __perf_evsel__calc_id_pos(u64 sample_type)
1298c2ecf20Sopenharmony_ci{
1308c2ecf20Sopenharmony_ci	int idx = 0;
1318c2ecf20Sopenharmony_ci
1328c2ecf20Sopenharmony_ci	if (sample_type & PERF_SAMPLE_IDENTIFIER)
1338c2ecf20Sopenharmony_ci		return 0;
1348c2ecf20Sopenharmony_ci
1358c2ecf20Sopenharmony_ci	if (!(sample_type & PERF_SAMPLE_ID))
1368c2ecf20Sopenharmony_ci		return -1;
1378c2ecf20Sopenharmony_ci
1388c2ecf20Sopenharmony_ci	if (sample_type & PERF_SAMPLE_IP)
1398c2ecf20Sopenharmony_ci		idx += 1;
1408c2ecf20Sopenharmony_ci
1418c2ecf20Sopenharmony_ci	if (sample_type & PERF_SAMPLE_TID)
1428c2ecf20Sopenharmony_ci		idx += 1;
1438c2ecf20Sopenharmony_ci
1448c2ecf20Sopenharmony_ci	if (sample_type & PERF_SAMPLE_TIME)
1458c2ecf20Sopenharmony_ci		idx += 1;
1468c2ecf20Sopenharmony_ci
1478c2ecf20Sopenharmony_ci	if (sample_type & PERF_SAMPLE_ADDR)
1488c2ecf20Sopenharmony_ci		idx += 1;
1498c2ecf20Sopenharmony_ci
1508c2ecf20Sopenharmony_ci	return idx;
1518c2ecf20Sopenharmony_ci}
1528c2ecf20Sopenharmony_ci
1538c2ecf20Sopenharmony_ci/**
1548c2ecf20Sopenharmony_ci * __perf_evsel__calc_is_pos - calculate is_pos.
1558c2ecf20Sopenharmony_ci * @sample_type: sample type
1568c2ecf20Sopenharmony_ci *
1578c2ecf20Sopenharmony_ci * This function returns the position (counting backwards) of the event id
1588c2ecf20Sopenharmony_ci * (PERF_SAMPLE_ID or PERF_SAMPLE_IDENTIFIER) in a non-sample event i.e. if
1598c2ecf20Sopenharmony_ci * sample_id_all is used there is an id sample appended to non-sample events.
1608c2ecf20Sopenharmony_ci */
1618c2ecf20Sopenharmony_cistatic int __perf_evsel__calc_is_pos(u64 sample_type)
1628c2ecf20Sopenharmony_ci{
1638c2ecf20Sopenharmony_ci	int idx = 1;
1648c2ecf20Sopenharmony_ci
1658c2ecf20Sopenharmony_ci	if (sample_type & PERF_SAMPLE_IDENTIFIER)
1668c2ecf20Sopenharmony_ci		return 1;
1678c2ecf20Sopenharmony_ci
1688c2ecf20Sopenharmony_ci	if (!(sample_type & PERF_SAMPLE_ID))
1698c2ecf20Sopenharmony_ci		return -1;
1708c2ecf20Sopenharmony_ci
1718c2ecf20Sopenharmony_ci	if (sample_type & PERF_SAMPLE_CPU)
1728c2ecf20Sopenharmony_ci		idx += 1;
1738c2ecf20Sopenharmony_ci
1748c2ecf20Sopenharmony_ci	if (sample_type & PERF_SAMPLE_STREAM_ID)
1758c2ecf20Sopenharmony_ci		idx += 1;
1768c2ecf20Sopenharmony_ci
1778c2ecf20Sopenharmony_ci	return idx;
1788c2ecf20Sopenharmony_ci}
1798c2ecf20Sopenharmony_ci
1808c2ecf20Sopenharmony_civoid evsel__calc_id_pos(struct evsel *evsel)
1818c2ecf20Sopenharmony_ci{
1828c2ecf20Sopenharmony_ci	evsel->id_pos = __perf_evsel__calc_id_pos(evsel->core.attr.sample_type);
1838c2ecf20Sopenharmony_ci	evsel->is_pos = __perf_evsel__calc_is_pos(evsel->core.attr.sample_type);
1848c2ecf20Sopenharmony_ci}
1858c2ecf20Sopenharmony_ci
1868c2ecf20Sopenharmony_civoid __evsel__set_sample_bit(struct evsel *evsel,
1878c2ecf20Sopenharmony_ci				  enum perf_event_sample_format bit)
1888c2ecf20Sopenharmony_ci{
1898c2ecf20Sopenharmony_ci	if (!(evsel->core.attr.sample_type & bit)) {
1908c2ecf20Sopenharmony_ci		evsel->core.attr.sample_type |= bit;
1918c2ecf20Sopenharmony_ci		evsel->sample_size += sizeof(u64);
1928c2ecf20Sopenharmony_ci		evsel__calc_id_pos(evsel);
1938c2ecf20Sopenharmony_ci	}
1948c2ecf20Sopenharmony_ci}
1958c2ecf20Sopenharmony_ci
1968c2ecf20Sopenharmony_civoid __evsel__reset_sample_bit(struct evsel *evsel,
1978c2ecf20Sopenharmony_ci				    enum perf_event_sample_format bit)
1988c2ecf20Sopenharmony_ci{
1998c2ecf20Sopenharmony_ci	if (evsel->core.attr.sample_type & bit) {
2008c2ecf20Sopenharmony_ci		evsel->core.attr.sample_type &= ~bit;
2018c2ecf20Sopenharmony_ci		evsel->sample_size -= sizeof(u64);
2028c2ecf20Sopenharmony_ci		evsel__calc_id_pos(evsel);
2038c2ecf20Sopenharmony_ci	}
2048c2ecf20Sopenharmony_ci}
2058c2ecf20Sopenharmony_ci
2068c2ecf20Sopenharmony_civoid evsel__set_sample_id(struct evsel *evsel,
2078c2ecf20Sopenharmony_ci			       bool can_sample_identifier)
2088c2ecf20Sopenharmony_ci{
2098c2ecf20Sopenharmony_ci	if (can_sample_identifier) {
2108c2ecf20Sopenharmony_ci		evsel__reset_sample_bit(evsel, ID);
2118c2ecf20Sopenharmony_ci		evsel__set_sample_bit(evsel, IDENTIFIER);
2128c2ecf20Sopenharmony_ci	} else {
2138c2ecf20Sopenharmony_ci		evsel__set_sample_bit(evsel, ID);
2148c2ecf20Sopenharmony_ci	}
2158c2ecf20Sopenharmony_ci	evsel->core.attr.read_format |= PERF_FORMAT_ID;
2168c2ecf20Sopenharmony_ci}
2178c2ecf20Sopenharmony_ci
2188c2ecf20Sopenharmony_ci/**
2198c2ecf20Sopenharmony_ci * evsel__is_function_event - Return whether given evsel is a function
2208c2ecf20Sopenharmony_ci * trace event
2218c2ecf20Sopenharmony_ci *
2228c2ecf20Sopenharmony_ci * @evsel - evsel selector to be tested
2238c2ecf20Sopenharmony_ci *
2248c2ecf20Sopenharmony_ci * Return %true if event is function trace event
2258c2ecf20Sopenharmony_ci */
2268c2ecf20Sopenharmony_cibool evsel__is_function_event(struct evsel *evsel)
2278c2ecf20Sopenharmony_ci{
2288c2ecf20Sopenharmony_ci#define FUNCTION_EVENT "ftrace:function"
2298c2ecf20Sopenharmony_ci
2308c2ecf20Sopenharmony_ci	return evsel->name &&
2318c2ecf20Sopenharmony_ci	       !strncmp(FUNCTION_EVENT, evsel->name, sizeof(FUNCTION_EVENT));
2328c2ecf20Sopenharmony_ci
2338c2ecf20Sopenharmony_ci#undef FUNCTION_EVENT
2348c2ecf20Sopenharmony_ci}
2358c2ecf20Sopenharmony_ci
2368c2ecf20Sopenharmony_civoid evsel__init(struct evsel *evsel,
2378c2ecf20Sopenharmony_ci		 struct perf_event_attr *attr, int idx)
2388c2ecf20Sopenharmony_ci{
2398c2ecf20Sopenharmony_ci	perf_evsel__init(&evsel->core, attr);
2408c2ecf20Sopenharmony_ci	evsel->idx	   = idx;
2418c2ecf20Sopenharmony_ci	evsel->tracking	   = !idx;
2428c2ecf20Sopenharmony_ci	evsel->leader	   = evsel;
2438c2ecf20Sopenharmony_ci	evsel->unit	   = "";
2448c2ecf20Sopenharmony_ci	evsel->scale	   = 1.0;
2458c2ecf20Sopenharmony_ci	evsel->max_events  = ULONG_MAX;
2468c2ecf20Sopenharmony_ci	evsel->evlist	   = NULL;
2478c2ecf20Sopenharmony_ci	evsel->bpf_obj	   = NULL;
2488c2ecf20Sopenharmony_ci	evsel->bpf_fd	   = -1;
2498c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&evsel->config_terms);
2508c2ecf20Sopenharmony_ci	perf_evsel__object.init(evsel);
2518c2ecf20Sopenharmony_ci	evsel->sample_size = __evsel__sample_size(attr->sample_type);
2528c2ecf20Sopenharmony_ci	evsel__calc_id_pos(evsel);
2538c2ecf20Sopenharmony_ci	evsel->cmdline_group_boundary = false;
2548c2ecf20Sopenharmony_ci	evsel->metric_expr   = NULL;
2558c2ecf20Sopenharmony_ci	evsel->metric_name   = NULL;
2568c2ecf20Sopenharmony_ci	evsel->metric_events = NULL;
2578c2ecf20Sopenharmony_ci	evsel->per_pkg_mask  = NULL;
2588c2ecf20Sopenharmony_ci	evsel->collect_stat  = false;
2598c2ecf20Sopenharmony_ci	evsel->pmu_name      = NULL;
2608c2ecf20Sopenharmony_ci}
2618c2ecf20Sopenharmony_ci
2628c2ecf20Sopenharmony_cistruct evsel *evsel__new_idx(struct perf_event_attr *attr, int idx)
2638c2ecf20Sopenharmony_ci{
2648c2ecf20Sopenharmony_ci	struct evsel *evsel = zalloc(perf_evsel__object.size);
2658c2ecf20Sopenharmony_ci
2668c2ecf20Sopenharmony_ci	if (!evsel)
2678c2ecf20Sopenharmony_ci		return NULL;
2688c2ecf20Sopenharmony_ci	evsel__init(evsel, attr, idx);
2698c2ecf20Sopenharmony_ci
2708c2ecf20Sopenharmony_ci	if (evsel__is_bpf_output(evsel)) {
2718c2ecf20Sopenharmony_ci		evsel->core.attr.sample_type |= (PERF_SAMPLE_RAW | PERF_SAMPLE_TIME |
2728c2ecf20Sopenharmony_ci					    PERF_SAMPLE_CPU | PERF_SAMPLE_PERIOD),
2738c2ecf20Sopenharmony_ci		evsel->core.attr.sample_period = 1;
2748c2ecf20Sopenharmony_ci	}
2758c2ecf20Sopenharmony_ci
2768c2ecf20Sopenharmony_ci	if (evsel__is_clock(evsel)) {
2778c2ecf20Sopenharmony_ci		/*
2788c2ecf20Sopenharmony_ci		 * The evsel->unit points to static alias->unit
2798c2ecf20Sopenharmony_ci		 * so it's ok to use static string in here.
2808c2ecf20Sopenharmony_ci		 */
2818c2ecf20Sopenharmony_ci		static const char *unit = "msec";
2828c2ecf20Sopenharmony_ci
2838c2ecf20Sopenharmony_ci		evsel->unit = unit;
2848c2ecf20Sopenharmony_ci		evsel->scale = 1e-6;
2858c2ecf20Sopenharmony_ci	}
2868c2ecf20Sopenharmony_ci
2878c2ecf20Sopenharmony_ci	return evsel;
2888c2ecf20Sopenharmony_ci}
2898c2ecf20Sopenharmony_ci
2908c2ecf20Sopenharmony_cistatic bool perf_event_can_profile_kernel(void)
2918c2ecf20Sopenharmony_ci{
2928c2ecf20Sopenharmony_ci	return perf_event_paranoid_check(1);
2938c2ecf20Sopenharmony_ci}
2948c2ecf20Sopenharmony_ci
2958c2ecf20Sopenharmony_cistruct evsel *evsel__new_cycles(bool precise)
2968c2ecf20Sopenharmony_ci{
2978c2ecf20Sopenharmony_ci	struct perf_event_attr attr = {
2988c2ecf20Sopenharmony_ci		.type	= PERF_TYPE_HARDWARE,
2998c2ecf20Sopenharmony_ci		.config	= PERF_COUNT_HW_CPU_CYCLES,
3008c2ecf20Sopenharmony_ci		.exclude_kernel	= !perf_event_can_profile_kernel(),
3018c2ecf20Sopenharmony_ci	};
3028c2ecf20Sopenharmony_ci	struct evsel *evsel;
3038c2ecf20Sopenharmony_ci
3048c2ecf20Sopenharmony_ci	event_attr_init(&attr);
3058c2ecf20Sopenharmony_ci
3068c2ecf20Sopenharmony_ci	if (!precise)
3078c2ecf20Sopenharmony_ci		goto new_event;
3088c2ecf20Sopenharmony_ci
3098c2ecf20Sopenharmony_ci	/*
3108c2ecf20Sopenharmony_ci	 * Now let the usual logic to set up the perf_event_attr defaults
3118c2ecf20Sopenharmony_ci	 * to kick in when we return and before perf_evsel__open() is called.
3128c2ecf20Sopenharmony_ci	 */
3138c2ecf20Sopenharmony_cinew_event:
3148c2ecf20Sopenharmony_ci	evsel = evsel__new(&attr);
3158c2ecf20Sopenharmony_ci	if (evsel == NULL)
3168c2ecf20Sopenharmony_ci		goto out;
3178c2ecf20Sopenharmony_ci
3188c2ecf20Sopenharmony_ci	evsel->precise_max = true;
3198c2ecf20Sopenharmony_ci
3208c2ecf20Sopenharmony_ci	/* use asprintf() because free(evsel) assumes name is allocated */
3218c2ecf20Sopenharmony_ci	if (asprintf(&evsel->name, "cycles%s%s%.*s",
3228c2ecf20Sopenharmony_ci		     (attr.precise_ip || attr.exclude_kernel) ? ":" : "",
3238c2ecf20Sopenharmony_ci		     attr.exclude_kernel ? "u" : "",
3248c2ecf20Sopenharmony_ci		     attr.precise_ip ? attr.precise_ip + 1 : 0, "ppp") < 0)
3258c2ecf20Sopenharmony_ci		goto error_free;
3268c2ecf20Sopenharmony_ciout:
3278c2ecf20Sopenharmony_ci	return evsel;
3288c2ecf20Sopenharmony_cierror_free:
3298c2ecf20Sopenharmony_ci	evsel__delete(evsel);
3308c2ecf20Sopenharmony_ci	evsel = NULL;
3318c2ecf20Sopenharmony_ci	goto out;
3328c2ecf20Sopenharmony_ci}
3338c2ecf20Sopenharmony_ci
3348c2ecf20Sopenharmony_cistatic int evsel__copy_config_terms(struct evsel *dst, struct evsel *src)
3358c2ecf20Sopenharmony_ci{
3368c2ecf20Sopenharmony_ci	struct evsel_config_term *pos, *tmp;
3378c2ecf20Sopenharmony_ci
3388c2ecf20Sopenharmony_ci	list_for_each_entry(pos, &src->config_terms, list) {
3398c2ecf20Sopenharmony_ci		tmp = malloc(sizeof(*tmp));
3408c2ecf20Sopenharmony_ci		if (tmp == NULL)
3418c2ecf20Sopenharmony_ci			return -ENOMEM;
3428c2ecf20Sopenharmony_ci
3438c2ecf20Sopenharmony_ci		*tmp = *pos;
3448c2ecf20Sopenharmony_ci		if (tmp->free_str) {
3458c2ecf20Sopenharmony_ci			tmp->val.str = strdup(pos->val.str);
3468c2ecf20Sopenharmony_ci			if (tmp->val.str == NULL) {
3478c2ecf20Sopenharmony_ci				free(tmp);
3488c2ecf20Sopenharmony_ci				return -ENOMEM;
3498c2ecf20Sopenharmony_ci			}
3508c2ecf20Sopenharmony_ci		}
3518c2ecf20Sopenharmony_ci		list_add_tail(&tmp->list, &dst->config_terms);
3528c2ecf20Sopenharmony_ci	}
3538c2ecf20Sopenharmony_ci	return 0;
3548c2ecf20Sopenharmony_ci}
3558c2ecf20Sopenharmony_ci
3568c2ecf20Sopenharmony_ci/**
3578c2ecf20Sopenharmony_ci * evsel__clone - create a new evsel copied from @orig
3588c2ecf20Sopenharmony_ci * @orig: original evsel
3598c2ecf20Sopenharmony_ci *
3608c2ecf20Sopenharmony_ci * The assumption is that @orig is not configured nor opened yet.
3618c2ecf20Sopenharmony_ci * So we only care about the attributes that can be set while it's parsed.
3628c2ecf20Sopenharmony_ci */
3638c2ecf20Sopenharmony_cistruct evsel *evsel__clone(struct evsel *orig)
3648c2ecf20Sopenharmony_ci{
3658c2ecf20Sopenharmony_ci	struct evsel *evsel;
3668c2ecf20Sopenharmony_ci
3678c2ecf20Sopenharmony_ci	BUG_ON(orig->core.fd);
3688c2ecf20Sopenharmony_ci	BUG_ON(orig->counts);
3698c2ecf20Sopenharmony_ci	BUG_ON(orig->priv);
3708c2ecf20Sopenharmony_ci	BUG_ON(orig->per_pkg_mask);
3718c2ecf20Sopenharmony_ci
3728c2ecf20Sopenharmony_ci	/* cannot handle BPF objects for now */
3738c2ecf20Sopenharmony_ci	if (orig->bpf_obj)
3748c2ecf20Sopenharmony_ci		return NULL;
3758c2ecf20Sopenharmony_ci
3768c2ecf20Sopenharmony_ci	evsel = evsel__new(&orig->core.attr);
3778c2ecf20Sopenharmony_ci	if (evsel == NULL)
3788c2ecf20Sopenharmony_ci		return NULL;
3798c2ecf20Sopenharmony_ci
3808c2ecf20Sopenharmony_ci	evsel->core.cpus = perf_cpu_map__get(orig->core.cpus);
3818c2ecf20Sopenharmony_ci	evsel->core.own_cpus = perf_cpu_map__get(orig->core.own_cpus);
3828c2ecf20Sopenharmony_ci	evsel->core.threads = perf_thread_map__get(orig->core.threads);
3838c2ecf20Sopenharmony_ci	evsel->core.nr_members = orig->core.nr_members;
3848c2ecf20Sopenharmony_ci	evsel->core.system_wide = orig->core.system_wide;
3858c2ecf20Sopenharmony_ci
3868c2ecf20Sopenharmony_ci	if (orig->name) {
3878c2ecf20Sopenharmony_ci		evsel->name = strdup(orig->name);
3888c2ecf20Sopenharmony_ci		if (evsel->name == NULL)
3898c2ecf20Sopenharmony_ci			goto out_err;
3908c2ecf20Sopenharmony_ci	}
3918c2ecf20Sopenharmony_ci	if (orig->group_name) {
3928c2ecf20Sopenharmony_ci		evsel->group_name = strdup(orig->group_name);
3938c2ecf20Sopenharmony_ci		if (evsel->group_name == NULL)
3948c2ecf20Sopenharmony_ci			goto out_err;
3958c2ecf20Sopenharmony_ci	}
3968c2ecf20Sopenharmony_ci	if (orig->pmu_name) {
3978c2ecf20Sopenharmony_ci		evsel->pmu_name = strdup(orig->pmu_name);
3988c2ecf20Sopenharmony_ci		if (evsel->pmu_name == NULL)
3998c2ecf20Sopenharmony_ci			goto out_err;
4008c2ecf20Sopenharmony_ci	}
4018c2ecf20Sopenharmony_ci	if (orig->filter) {
4028c2ecf20Sopenharmony_ci		evsel->filter = strdup(orig->filter);
4038c2ecf20Sopenharmony_ci		if (evsel->filter == NULL)
4048c2ecf20Sopenharmony_ci			goto out_err;
4058c2ecf20Sopenharmony_ci	}
4068c2ecf20Sopenharmony_ci	evsel->cgrp = cgroup__get(orig->cgrp);
4078c2ecf20Sopenharmony_ci	evsel->tp_format = orig->tp_format;
4088c2ecf20Sopenharmony_ci	evsel->handler = orig->handler;
4098c2ecf20Sopenharmony_ci	evsel->leader = orig->leader;
4108c2ecf20Sopenharmony_ci
4118c2ecf20Sopenharmony_ci	evsel->max_events = orig->max_events;
4128c2ecf20Sopenharmony_ci	evsel->tool_event = orig->tool_event;
4138c2ecf20Sopenharmony_ci	evsel->unit = orig->unit;
4148c2ecf20Sopenharmony_ci	evsel->scale = orig->scale;
4158c2ecf20Sopenharmony_ci	evsel->snapshot = orig->snapshot;
4168c2ecf20Sopenharmony_ci	evsel->per_pkg = orig->per_pkg;
4178c2ecf20Sopenharmony_ci	evsel->percore = orig->percore;
4188c2ecf20Sopenharmony_ci	evsel->precise_max = orig->precise_max;
4198c2ecf20Sopenharmony_ci	evsel->use_uncore_alias = orig->use_uncore_alias;
4208c2ecf20Sopenharmony_ci	evsel->is_libpfm_event = orig->is_libpfm_event;
4218c2ecf20Sopenharmony_ci
4228c2ecf20Sopenharmony_ci	evsel->exclude_GH = orig->exclude_GH;
4238c2ecf20Sopenharmony_ci	evsel->sample_read = orig->sample_read;
4248c2ecf20Sopenharmony_ci	evsel->auto_merge_stats = orig->auto_merge_stats;
4258c2ecf20Sopenharmony_ci	evsel->collect_stat = orig->collect_stat;
4268c2ecf20Sopenharmony_ci	evsel->weak_group = orig->weak_group;
4278c2ecf20Sopenharmony_ci
4288c2ecf20Sopenharmony_ci	if (evsel__copy_config_terms(evsel, orig) < 0)
4298c2ecf20Sopenharmony_ci		goto out_err;
4308c2ecf20Sopenharmony_ci
4318c2ecf20Sopenharmony_ci	return evsel;
4328c2ecf20Sopenharmony_ci
4338c2ecf20Sopenharmony_ciout_err:
4348c2ecf20Sopenharmony_ci	evsel__delete(evsel);
4358c2ecf20Sopenharmony_ci	return NULL;
4368c2ecf20Sopenharmony_ci}
4378c2ecf20Sopenharmony_ci
4388c2ecf20Sopenharmony_ci/*
4398c2ecf20Sopenharmony_ci * Returns pointer with encoded error via <linux/err.h> interface.
4408c2ecf20Sopenharmony_ci */
4418c2ecf20Sopenharmony_cistruct evsel *evsel__newtp_idx(const char *sys, const char *name, int idx)
4428c2ecf20Sopenharmony_ci{
4438c2ecf20Sopenharmony_ci	struct evsel *evsel = zalloc(perf_evsel__object.size);
4448c2ecf20Sopenharmony_ci	int err = -ENOMEM;
4458c2ecf20Sopenharmony_ci
4468c2ecf20Sopenharmony_ci	if (evsel == NULL) {
4478c2ecf20Sopenharmony_ci		goto out_err;
4488c2ecf20Sopenharmony_ci	} else {
4498c2ecf20Sopenharmony_ci		struct perf_event_attr attr = {
4508c2ecf20Sopenharmony_ci			.type	       = PERF_TYPE_TRACEPOINT,
4518c2ecf20Sopenharmony_ci			.sample_type   = (PERF_SAMPLE_RAW | PERF_SAMPLE_TIME |
4528c2ecf20Sopenharmony_ci					  PERF_SAMPLE_CPU | PERF_SAMPLE_PERIOD),
4538c2ecf20Sopenharmony_ci		};
4548c2ecf20Sopenharmony_ci
4558c2ecf20Sopenharmony_ci		if (asprintf(&evsel->name, "%s:%s", sys, name) < 0)
4568c2ecf20Sopenharmony_ci			goto out_free;
4578c2ecf20Sopenharmony_ci
4588c2ecf20Sopenharmony_ci		evsel->tp_format = trace_event__tp_format(sys, name);
4598c2ecf20Sopenharmony_ci		if (IS_ERR(evsel->tp_format)) {
4608c2ecf20Sopenharmony_ci			err = PTR_ERR(evsel->tp_format);
4618c2ecf20Sopenharmony_ci			goto out_free;
4628c2ecf20Sopenharmony_ci		}
4638c2ecf20Sopenharmony_ci
4648c2ecf20Sopenharmony_ci		event_attr_init(&attr);
4658c2ecf20Sopenharmony_ci		attr.config = evsel->tp_format->id;
4668c2ecf20Sopenharmony_ci		attr.sample_period = 1;
4678c2ecf20Sopenharmony_ci		evsel__init(evsel, &attr, idx);
4688c2ecf20Sopenharmony_ci	}
4698c2ecf20Sopenharmony_ci
4708c2ecf20Sopenharmony_ci	return evsel;
4718c2ecf20Sopenharmony_ci
4728c2ecf20Sopenharmony_ciout_free:
4738c2ecf20Sopenharmony_ci	zfree(&evsel->name);
4748c2ecf20Sopenharmony_ci	free(evsel);
4758c2ecf20Sopenharmony_ciout_err:
4768c2ecf20Sopenharmony_ci	return ERR_PTR(err);
4778c2ecf20Sopenharmony_ci}
4788c2ecf20Sopenharmony_ci
4798c2ecf20Sopenharmony_ciconst char *evsel__hw_names[PERF_COUNT_HW_MAX] = {
4808c2ecf20Sopenharmony_ci	"cycles",
4818c2ecf20Sopenharmony_ci	"instructions",
4828c2ecf20Sopenharmony_ci	"cache-references",
4838c2ecf20Sopenharmony_ci	"cache-misses",
4848c2ecf20Sopenharmony_ci	"branches",
4858c2ecf20Sopenharmony_ci	"branch-misses",
4868c2ecf20Sopenharmony_ci	"bus-cycles",
4878c2ecf20Sopenharmony_ci	"stalled-cycles-frontend",
4888c2ecf20Sopenharmony_ci	"stalled-cycles-backend",
4898c2ecf20Sopenharmony_ci	"ref-cycles",
4908c2ecf20Sopenharmony_ci};
4918c2ecf20Sopenharmony_ci
4928c2ecf20Sopenharmony_cistatic const char *__evsel__hw_name(u64 config)
4938c2ecf20Sopenharmony_ci{
4948c2ecf20Sopenharmony_ci	if (config < PERF_COUNT_HW_MAX && evsel__hw_names[config])
4958c2ecf20Sopenharmony_ci		return evsel__hw_names[config];
4968c2ecf20Sopenharmony_ci
4978c2ecf20Sopenharmony_ci	return "unknown-hardware";
4988c2ecf20Sopenharmony_ci}
4998c2ecf20Sopenharmony_ci
5008c2ecf20Sopenharmony_cistatic int perf_evsel__add_modifiers(struct evsel *evsel, char *bf, size_t size)
5018c2ecf20Sopenharmony_ci{
5028c2ecf20Sopenharmony_ci	int colon = 0, r = 0;
5038c2ecf20Sopenharmony_ci	struct perf_event_attr *attr = &evsel->core.attr;
5048c2ecf20Sopenharmony_ci	bool exclude_guest_default = false;
5058c2ecf20Sopenharmony_ci
5068c2ecf20Sopenharmony_ci#define MOD_PRINT(context, mod)	do {					\
5078c2ecf20Sopenharmony_ci		if (!attr->exclude_##context) {				\
5088c2ecf20Sopenharmony_ci			if (!colon) colon = ++r;			\
5098c2ecf20Sopenharmony_ci			r += scnprintf(bf + r, size - r, "%c", mod);	\
5108c2ecf20Sopenharmony_ci		} } while(0)
5118c2ecf20Sopenharmony_ci
5128c2ecf20Sopenharmony_ci	if (attr->exclude_kernel || attr->exclude_user || attr->exclude_hv) {
5138c2ecf20Sopenharmony_ci		MOD_PRINT(kernel, 'k');
5148c2ecf20Sopenharmony_ci		MOD_PRINT(user, 'u');
5158c2ecf20Sopenharmony_ci		MOD_PRINT(hv, 'h');
5168c2ecf20Sopenharmony_ci		exclude_guest_default = true;
5178c2ecf20Sopenharmony_ci	}
5188c2ecf20Sopenharmony_ci
5198c2ecf20Sopenharmony_ci	if (attr->precise_ip) {
5208c2ecf20Sopenharmony_ci		if (!colon)
5218c2ecf20Sopenharmony_ci			colon = ++r;
5228c2ecf20Sopenharmony_ci		r += scnprintf(bf + r, size - r, "%.*s", attr->precise_ip, "ppp");
5238c2ecf20Sopenharmony_ci		exclude_guest_default = true;
5248c2ecf20Sopenharmony_ci	}
5258c2ecf20Sopenharmony_ci
5268c2ecf20Sopenharmony_ci	if (attr->exclude_host || attr->exclude_guest == exclude_guest_default) {
5278c2ecf20Sopenharmony_ci		MOD_PRINT(host, 'H');
5288c2ecf20Sopenharmony_ci		MOD_PRINT(guest, 'G');
5298c2ecf20Sopenharmony_ci	}
5308c2ecf20Sopenharmony_ci#undef MOD_PRINT
5318c2ecf20Sopenharmony_ci	if (colon)
5328c2ecf20Sopenharmony_ci		bf[colon - 1] = ':';
5338c2ecf20Sopenharmony_ci	return r;
5348c2ecf20Sopenharmony_ci}
5358c2ecf20Sopenharmony_ci
5368c2ecf20Sopenharmony_cistatic int evsel__hw_name(struct evsel *evsel, char *bf, size_t size)
5378c2ecf20Sopenharmony_ci{
5388c2ecf20Sopenharmony_ci	int r = scnprintf(bf, size, "%s", __evsel__hw_name(evsel->core.attr.config));
5398c2ecf20Sopenharmony_ci	return r + perf_evsel__add_modifiers(evsel, bf + r, size - r);
5408c2ecf20Sopenharmony_ci}
5418c2ecf20Sopenharmony_ci
5428c2ecf20Sopenharmony_ciconst char *evsel__sw_names[PERF_COUNT_SW_MAX] = {
5438c2ecf20Sopenharmony_ci	"cpu-clock",
5448c2ecf20Sopenharmony_ci	"task-clock",
5458c2ecf20Sopenharmony_ci	"page-faults",
5468c2ecf20Sopenharmony_ci	"context-switches",
5478c2ecf20Sopenharmony_ci	"cpu-migrations",
5488c2ecf20Sopenharmony_ci	"minor-faults",
5498c2ecf20Sopenharmony_ci	"major-faults",
5508c2ecf20Sopenharmony_ci	"alignment-faults",
5518c2ecf20Sopenharmony_ci	"emulation-faults",
5528c2ecf20Sopenharmony_ci	"dummy",
5538c2ecf20Sopenharmony_ci};
5548c2ecf20Sopenharmony_ci
5558c2ecf20Sopenharmony_cistatic const char *__evsel__sw_name(u64 config)
5568c2ecf20Sopenharmony_ci{
5578c2ecf20Sopenharmony_ci	if (config < PERF_COUNT_SW_MAX && evsel__sw_names[config])
5588c2ecf20Sopenharmony_ci		return evsel__sw_names[config];
5598c2ecf20Sopenharmony_ci	return "unknown-software";
5608c2ecf20Sopenharmony_ci}
5618c2ecf20Sopenharmony_ci
5628c2ecf20Sopenharmony_cistatic int evsel__sw_name(struct evsel *evsel, char *bf, size_t size)
5638c2ecf20Sopenharmony_ci{
5648c2ecf20Sopenharmony_ci	int r = scnprintf(bf, size, "%s", __evsel__sw_name(evsel->core.attr.config));
5658c2ecf20Sopenharmony_ci	return r + perf_evsel__add_modifiers(evsel, bf + r, size - r);
5668c2ecf20Sopenharmony_ci}
5678c2ecf20Sopenharmony_ci
5688c2ecf20Sopenharmony_cistatic int __evsel__bp_name(char *bf, size_t size, u64 addr, u64 type)
5698c2ecf20Sopenharmony_ci{
5708c2ecf20Sopenharmony_ci	int r;
5718c2ecf20Sopenharmony_ci
5728c2ecf20Sopenharmony_ci	r = scnprintf(bf, size, "mem:0x%" PRIx64 ":", addr);
5738c2ecf20Sopenharmony_ci
5748c2ecf20Sopenharmony_ci	if (type & HW_BREAKPOINT_R)
5758c2ecf20Sopenharmony_ci		r += scnprintf(bf + r, size - r, "r");
5768c2ecf20Sopenharmony_ci
5778c2ecf20Sopenharmony_ci	if (type & HW_BREAKPOINT_W)
5788c2ecf20Sopenharmony_ci		r += scnprintf(bf + r, size - r, "w");
5798c2ecf20Sopenharmony_ci
5808c2ecf20Sopenharmony_ci	if (type & HW_BREAKPOINT_X)
5818c2ecf20Sopenharmony_ci		r += scnprintf(bf + r, size - r, "x");
5828c2ecf20Sopenharmony_ci
5838c2ecf20Sopenharmony_ci	return r;
5848c2ecf20Sopenharmony_ci}
5858c2ecf20Sopenharmony_ci
5868c2ecf20Sopenharmony_cistatic int evsel__bp_name(struct evsel *evsel, char *bf, size_t size)
5878c2ecf20Sopenharmony_ci{
5888c2ecf20Sopenharmony_ci	struct perf_event_attr *attr = &evsel->core.attr;
5898c2ecf20Sopenharmony_ci	int r = __evsel__bp_name(bf, size, attr->bp_addr, attr->bp_type);
5908c2ecf20Sopenharmony_ci	return r + perf_evsel__add_modifiers(evsel, bf + r, size - r);
5918c2ecf20Sopenharmony_ci}
5928c2ecf20Sopenharmony_ci
5938c2ecf20Sopenharmony_ciconst char *evsel__hw_cache[PERF_COUNT_HW_CACHE_MAX][EVSEL__MAX_ALIASES] = {
5948c2ecf20Sopenharmony_ci { "L1-dcache",	"l1-d",		"l1d",		"L1-data",		},
5958c2ecf20Sopenharmony_ci { "L1-icache",	"l1-i",		"l1i",		"L1-instruction",	},
5968c2ecf20Sopenharmony_ci { "LLC",	"L2",							},
5978c2ecf20Sopenharmony_ci { "dTLB",	"d-tlb",	"Data-TLB",				},
5988c2ecf20Sopenharmony_ci { "iTLB",	"i-tlb",	"Instruction-TLB",			},
5998c2ecf20Sopenharmony_ci { "branch",	"branches",	"bpu",		"btb",		"bpc",	},
6008c2ecf20Sopenharmony_ci { "node",								},
6018c2ecf20Sopenharmony_ci};
6028c2ecf20Sopenharmony_ci
6038c2ecf20Sopenharmony_ciconst char *evsel__hw_cache_op[PERF_COUNT_HW_CACHE_OP_MAX][EVSEL__MAX_ALIASES] = {
6048c2ecf20Sopenharmony_ci { "load",	"loads",	"read",					},
6058c2ecf20Sopenharmony_ci { "store",	"stores",	"write",				},
6068c2ecf20Sopenharmony_ci { "prefetch",	"prefetches",	"speculative-read", "speculative-load",	},
6078c2ecf20Sopenharmony_ci};
6088c2ecf20Sopenharmony_ci
6098c2ecf20Sopenharmony_ciconst char *evsel__hw_cache_result[PERF_COUNT_HW_CACHE_RESULT_MAX][EVSEL__MAX_ALIASES] = {
6108c2ecf20Sopenharmony_ci { "refs",	"Reference",	"ops",		"access",		},
6118c2ecf20Sopenharmony_ci { "misses",	"miss",							},
6128c2ecf20Sopenharmony_ci};
6138c2ecf20Sopenharmony_ci
6148c2ecf20Sopenharmony_ci#define C(x)		PERF_COUNT_HW_CACHE_##x
6158c2ecf20Sopenharmony_ci#define CACHE_READ	(1 << C(OP_READ))
6168c2ecf20Sopenharmony_ci#define CACHE_WRITE	(1 << C(OP_WRITE))
6178c2ecf20Sopenharmony_ci#define CACHE_PREFETCH	(1 << C(OP_PREFETCH))
6188c2ecf20Sopenharmony_ci#define COP(x)		(1 << x)
6198c2ecf20Sopenharmony_ci
6208c2ecf20Sopenharmony_ci/*
6218c2ecf20Sopenharmony_ci * cache operartion stat
6228c2ecf20Sopenharmony_ci * L1I : Read and prefetch only
6238c2ecf20Sopenharmony_ci * ITLB and BPU : Read-only
6248c2ecf20Sopenharmony_ci */
6258c2ecf20Sopenharmony_cistatic unsigned long evsel__hw_cache_stat[C(MAX)] = {
6268c2ecf20Sopenharmony_ci [C(L1D)]	= (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH),
6278c2ecf20Sopenharmony_ci [C(L1I)]	= (CACHE_READ | CACHE_PREFETCH),
6288c2ecf20Sopenharmony_ci [C(LL)]	= (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH),
6298c2ecf20Sopenharmony_ci [C(DTLB)]	= (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH),
6308c2ecf20Sopenharmony_ci [C(ITLB)]	= (CACHE_READ),
6318c2ecf20Sopenharmony_ci [C(BPU)]	= (CACHE_READ),
6328c2ecf20Sopenharmony_ci [C(NODE)]	= (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH),
6338c2ecf20Sopenharmony_ci};
6348c2ecf20Sopenharmony_ci
6358c2ecf20Sopenharmony_cibool evsel__is_cache_op_valid(u8 type, u8 op)
6368c2ecf20Sopenharmony_ci{
6378c2ecf20Sopenharmony_ci	if (evsel__hw_cache_stat[type] & COP(op))
6388c2ecf20Sopenharmony_ci		return true;	/* valid */
6398c2ecf20Sopenharmony_ci	else
6408c2ecf20Sopenharmony_ci		return false;	/* invalid */
6418c2ecf20Sopenharmony_ci}
6428c2ecf20Sopenharmony_ci
6438c2ecf20Sopenharmony_ciint __evsel__hw_cache_type_op_res_name(u8 type, u8 op, u8 result, char *bf, size_t size)
6448c2ecf20Sopenharmony_ci{
6458c2ecf20Sopenharmony_ci	if (result) {
6468c2ecf20Sopenharmony_ci		return scnprintf(bf, size, "%s-%s-%s", evsel__hw_cache[type][0],
6478c2ecf20Sopenharmony_ci				 evsel__hw_cache_op[op][0],
6488c2ecf20Sopenharmony_ci				 evsel__hw_cache_result[result][0]);
6498c2ecf20Sopenharmony_ci	}
6508c2ecf20Sopenharmony_ci
6518c2ecf20Sopenharmony_ci	return scnprintf(bf, size, "%s-%s", evsel__hw_cache[type][0],
6528c2ecf20Sopenharmony_ci			 evsel__hw_cache_op[op][1]);
6538c2ecf20Sopenharmony_ci}
6548c2ecf20Sopenharmony_ci
6558c2ecf20Sopenharmony_cistatic int __evsel__hw_cache_name(u64 config, char *bf, size_t size)
6568c2ecf20Sopenharmony_ci{
6578c2ecf20Sopenharmony_ci	u8 op, result, type = (config >>  0) & 0xff;
6588c2ecf20Sopenharmony_ci	const char *err = "unknown-ext-hardware-cache-type";
6598c2ecf20Sopenharmony_ci
6608c2ecf20Sopenharmony_ci	if (type >= PERF_COUNT_HW_CACHE_MAX)
6618c2ecf20Sopenharmony_ci		goto out_err;
6628c2ecf20Sopenharmony_ci
6638c2ecf20Sopenharmony_ci	op = (config >>  8) & 0xff;
6648c2ecf20Sopenharmony_ci	err = "unknown-ext-hardware-cache-op";
6658c2ecf20Sopenharmony_ci	if (op >= PERF_COUNT_HW_CACHE_OP_MAX)
6668c2ecf20Sopenharmony_ci		goto out_err;
6678c2ecf20Sopenharmony_ci
6688c2ecf20Sopenharmony_ci	result = (config >> 16) & 0xff;
6698c2ecf20Sopenharmony_ci	err = "unknown-ext-hardware-cache-result";
6708c2ecf20Sopenharmony_ci	if (result >= PERF_COUNT_HW_CACHE_RESULT_MAX)
6718c2ecf20Sopenharmony_ci		goto out_err;
6728c2ecf20Sopenharmony_ci
6738c2ecf20Sopenharmony_ci	err = "invalid-cache";
6748c2ecf20Sopenharmony_ci	if (!evsel__is_cache_op_valid(type, op))
6758c2ecf20Sopenharmony_ci		goto out_err;
6768c2ecf20Sopenharmony_ci
6778c2ecf20Sopenharmony_ci	return __evsel__hw_cache_type_op_res_name(type, op, result, bf, size);
6788c2ecf20Sopenharmony_ciout_err:
6798c2ecf20Sopenharmony_ci	return scnprintf(bf, size, "%s", err);
6808c2ecf20Sopenharmony_ci}
6818c2ecf20Sopenharmony_ci
6828c2ecf20Sopenharmony_cistatic int evsel__hw_cache_name(struct evsel *evsel, char *bf, size_t size)
6838c2ecf20Sopenharmony_ci{
6848c2ecf20Sopenharmony_ci	int ret = __evsel__hw_cache_name(evsel->core.attr.config, bf, size);
6858c2ecf20Sopenharmony_ci	return ret + perf_evsel__add_modifiers(evsel, bf + ret, size - ret);
6868c2ecf20Sopenharmony_ci}
6878c2ecf20Sopenharmony_ci
6888c2ecf20Sopenharmony_cistatic int evsel__raw_name(struct evsel *evsel, char *bf, size_t size)
6898c2ecf20Sopenharmony_ci{
6908c2ecf20Sopenharmony_ci	int ret = scnprintf(bf, size, "raw 0x%" PRIx64, evsel->core.attr.config);
6918c2ecf20Sopenharmony_ci	return ret + perf_evsel__add_modifiers(evsel, bf + ret, size - ret);
6928c2ecf20Sopenharmony_ci}
6938c2ecf20Sopenharmony_ci
6948c2ecf20Sopenharmony_cistatic int evsel__tool_name(char *bf, size_t size)
6958c2ecf20Sopenharmony_ci{
6968c2ecf20Sopenharmony_ci	int ret = scnprintf(bf, size, "duration_time");
6978c2ecf20Sopenharmony_ci	return ret;
6988c2ecf20Sopenharmony_ci}
6998c2ecf20Sopenharmony_ci
7008c2ecf20Sopenharmony_ciconst char *evsel__name(struct evsel *evsel)
7018c2ecf20Sopenharmony_ci{
7028c2ecf20Sopenharmony_ci	char bf[128];
7038c2ecf20Sopenharmony_ci
7048c2ecf20Sopenharmony_ci	if (!evsel)
7058c2ecf20Sopenharmony_ci		goto out_unknown;
7068c2ecf20Sopenharmony_ci
7078c2ecf20Sopenharmony_ci	if (evsel->name)
7088c2ecf20Sopenharmony_ci		return evsel->name;
7098c2ecf20Sopenharmony_ci
7108c2ecf20Sopenharmony_ci	switch (evsel->core.attr.type) {
7118c2ecf20Sopenharmony_ci	case PERF_TYPE_RAW:
7128c2ecf20Sopenharmony_ci		evsel__raw_name(evsel, bf, sizeof(bf));
7138c2ecf20Sopenharmony_ci		break;
7148c2ecf20Sopenharmony_ci
7158c2ecf20Sopenharmony_ci	case PERF_TYPE_HARDWARE:
7168c2ecf20Sopenharmony_ci		evsel__hw_name(evsel, bf, sizeof(bf));
7178c2ecf20Sopenharmony_ci		break;
7188c2ecf20Sopenharmony_ci
7198c2ecf20Sopenharmony_ci	case PERF_TYPE_HW_CACHE:
7208c2ecf20Sopenharmony_ci		evsel__hw_cache_name(evsel, bf, sizeof(bf));
7218c2ecf20Sopenharmony_ci		break;
7228c2ecf20Sopenharmony_ci
7238c2ecf20Sopenharmony_ci	case PERF_TYPE_SOFTWARE:
7248c2ecf20Sopenharmony_ci		if (evsel->tool_event)
7258c2ecf20Sopenharmony_ci			evsel__tool_name(bf, sizeof(bf));
7268c2ecf20Sopenharmony_ci		else
7278c2ecf20Sopenharmony_ci			evsel__sw_name(evsel, bf, sizeof(bf));
7288c2ecf20Sopenharmony_ci		break;
7298c2ecf20Sopenharmony_ci
7308c2ecf20Sopenharmony_ci	case PERF_TYPE_TRACEPOINT:
7318c2ecf20Sopenharmony_ci		scnprintf(bf, sizeof(bf), "%s", "unknown tracepoint");
7328c2ecf20Sopenharmony_ci		break;
7338c2ecf20Sopenharmony_ci
7348c2ecf20Sopenharmony_ci	case PERF_TYPE_BREAKPOINT:
7358c2ecf20Sopenharmony_ci		evsel__bp_name(evsel, bf, sizeof(bf));
7368c2ecf20Sopenharmony_ci		break;
7378c2ecf20Sopenharmony_ci
7388c2ecf20Sopenharmony_ci	default:
7398c2ecf20Sopenharmony_ci		scnprintf(bf, sizeof(bf), "unknown attr type: %d",
7408c2ecf20Sopenharmony_ci			  evsel->core.attr.type);
7418c2ecf20Sopenharmony_ci		break;
7428c2ecf20Sopenharmony_ci	}
7438c2ecf20Sopenharmony_ci
7448c2ecf20Sopenharmony_ci	evsel->name = strdup(bf);
7458c2ecf20Sopenharmony_ci
7468c2ecf20Sopenharmony_ci	if (evsel->name)
7478c2ecf20Sopenharmony_ci		return evsel->name;
7488c2ecf20Sopenharmony_ciout_unknown:
7498c2ecf20Sopenharmony_ci	return "unknown";
7508c2ecf20Sopenharmony_ci}
7518c2ecf20Sopenharmony_ci
7528c2ecf20Sopenharmony_ciconst char *evsel__group_name(struct evsel *evsel)
7538c2ecf20Sopenharmony_ci{
7548c2ecf20Sopenharmony_ci	return evsel->group_name ?: "anon group";
7558c2ecf20Sopenharmony_ci}
7568c2ecf20Sopenharmony_ci
7578c2ecf20Sopenharmony_ci/*
7588c2ecf20Sopenharmony_ci * Returns the group details for the specified leader,
7598c2ecf20Sopenharmony_ci * with following rules.
7608c2ecf20Sopenharmony_ci *
7618c2ecf20Sopenharmony_ci *  For record -e '{cycles,instructions}'
7628c2ecf20Sopenharmony_ci *    'anon group { cycles:u, instructions:u }'
7638c2ecf20Sopenharmony_ci *
7648c2ecf20Sopenharmony_ci *  For record -e 'cycles,instructions' and report --group
7658c2ecf20Sopenharmony_ci *    'cycles:u, instructions:u'
7668c2ecf20Sopenharmony_ci */
7678c2ecf20Sopenharmony_ciint evsel__group_desc(struct evsel *evsel, char *buf, size_t size)
7688c2ecf20Sopenharmony_ci{
7698c2ecf20Sopenharmony_ci	int ret = 0;
7708c2ecf20Sopenharmony_ci	struct evsel *pos;
7718c2ecf20Sopenharmony_ci	const char *group_name = evsel__group_name(evsel);
7728c2ecf20Sopenharmony_ci
7738c2ecf20Sopenharmony_ci	if (!evsel->forced_leader)
7748c2ecf20Sopenharmony_ci		ret = scnprintf(buf, size, "%s { ", group_name);
7758c2ecf20Sopenharmony_ci
7768c2ecf20Sopenharmony_ci	ret += scnprintf(buf + ret, size - ret, "%s", evsel__name(evsel));
7778c2ecf20Sopenharmony_ci
7788c2ecf20Sopenharmony_ci	for_each_group_member(pos, evsel)
7798c2ecf20Sopenharmony_ci		ret += scnprintf(buf + ret, size - ret, ", %s", evsel__name(pos));
7808c2ecf20Sopenharmony_ci
7818c2ecf20Sopenharmony_ci	if (!evsel->forced_leader)
7828c2ecf20Sopenharmony_ci		ret += scnprintf(buf + ret, size - ret, " }");
7838c2ecf20Sopenharmony_ci
7848c2ecf20Sopenharmony_ci	return ret;
7858c2ecf20Sopenharmony_ci}
7868c2ecf20Sopenharmony_ci
7878c2ecf20Sopenharmony_cistatic void __evsel__config_callchain(struct evsel *evsel, struct record_opts *opts,
7888c2ecf20Sopenharmony_ci				      struct callchain_param *param)
7898c2ecf20Sopenharmony_ci{
7908c2ecf20Sopenharmony_ci	bool function = evsel__is_function_event(evsel);
7918c2ecf20Sopenharmony_ci	struct perf_event_attr *attr = &evsel->core.attr;
7928c2ecf20Sopenharmony_ci
7938c2ecf20Sopenharmony_ci	evsel__set_sample_bit(evsel, CALLCHAIN);
7948c2ecf20Sopenharmony_ci
7958c2ecf20Sopenharmony_ci	attr->sample_max_stack = param->max_stack;
7968c2ecf20Sopenharmony_ci
7978c2ecf20Sopenharmony_ci	if (opts->kernel_callchains)
7988c2ecf20Sopenharmony_ci		attr->exclude_callchain_user = 1;
7998c2ecf20Sopenharmony_ci	if (opts->user_callchains)
8008c2ecf20Sopenharmony_ci		attr->exclude_callchain_kernel = 1;
8018c2ecf20Sopenharmony_ci	if (param->record_mode == CALLCHAIN_LBR) {
8028c2ecf20Sopenharmony_ci		if (!opts->branch_stack) {
8038c2ecf20Sopenharmony_ci			if (attr->exclude_user) {
8048c2ecf20Sopenharmony_ci				pr_warning("LBR callstack option is only available "
8058c2ecf20Sopenharmony_ci					   "to get user callchain information. "
8068c2ecf20Sopenharmony_ci					   "Falling back to framepointers.\n");
8078c2ecf20Sopenharmony_ci			} else {
8088c2ecf20Sopenharmony_ci				evsel__set_sample_bit(evsel, BRANCH_STACK);
8098c2ecf20Sopenharmony_ci				attr->branch_sample_type = PERF_SAMPLE_BRANCH_USER |
8108c2ecf20Sopenharmony_ci							PERF_SAMPLE_BRANCH_CALL_STACK |
8118c2ecf20Sopenharmony_ci							PERF_SAMPLE_BRANCH_NO_CYCLES |
8128c2ecf20Sopenharmony_ci							PERF_SAMPLE_BRANCH_NO_FLAGS |
8138c2ecf20Sopenharmony_ci							PERF_SAMPLE_BRANCH_HW_INDEX;
8148c2ecf20Sopenharmony_ci			}
8158c2ecf20Sopenharmony_ci		} else
8168c2ecf20Sopenharmony_ci			 pr_warning("Cannot use LBR callstack with branch stack. "
8178c2ecf20Sopenharmony_ci				    "Falling back to framepointers.\n");
8188c2ecf20Sopenharmony_ci	}
8198c2ecf20Sopenharmony_ci
8208c2ecf20Sopenharmony_ci	if (param->record_mode == CALLCHAIN_DWARF) {
8218c2ecf20Sopenharmony_ci		if (!function) {
8228c2ecf20Sopenharmony_ci			evsel__set_sample_bit(evsel, REGS_USER);
8238c2ecf20Sopenharmony_ci			evsel__set_sample_bit(evsel, STACK_USER);
8248c2ecf20Sopenharmony_ci			if (opts->sample_user_regs && DWARF_MINIMAL_REGS != PERF_REGS_MASK) {
8258c2ecf20Sopenharmony_ci				attr->sample_regs_user |= DWARF_MINIMAL_REGS;
8268c2ecf20Sopenharmony_ci				pr_warning("WARNING: The use of --call-graph=dwarf may require all the user registers, "
8278c2ecf20Sopenharmony_ci					   "specifying a subset with --user-regs may render DWARF unwinding unreliable, "
8288c2ecf20Sopenharmony_ci					   "so the minimal registers set (IP, SP) is explicitly forced.\n");
8298c2ecf20Sopenharmony_ci			} else {
8308c2ecf20Sopenharmony_ci				attr->sample_regs_user |= PERF_REGS_MASK;
8318c2ecf20Sopenharmony_ci			}
8328c2ecf20Sopenharmony_ci			attr->sample_stack_user = param->dump_size;
8338c2ecf20Sopenharmony_ci			attr->exclude_callchain_user = 1;
8348c2ecf20Sopenharmony_ci		} else {
8358c2ecf20Sopenharmony_ci			pr_info("Cannot use DWARF unwind for function trace event,"
8368c2ecf20Sopenharmony_ci				" falling back to framepointers.\n");
8378c2ecf20Sopenharmony_ci		}
8388c2ecf20Sopenharmony_ci	}
8398c2ecf20Sopenharmony_ci
8408c2ecf20Sopenharmony_ci	if (function) {
8418c2ecf20Sopenharmony_ci		pr_info("Disabling user space callchains for function trace event.\n");
8428c2ecf20Sopenharmony_ci		attr->exclude_callchain_user = 1;
8438c2ecf20Sopenharmony_ci	}
8448c2ecf20Sopenharmony_ci}
8458c2ecf20Sopenharmony_ci
8468c2ecf20Sopenharmony_civoid evsel__config_callchain(struct evsel *evsel, struct record_opts *opts,
8478c2ecf20Sopenharmony_ci			     struct callchain_param *param)
8488c2ecf20Sopenharmony_ci{
8498c2ecf20Sopenharmony_ci	if (param->enabled)
8508c2ecf20Sopenharmony_ci		return __evsel__config_callchain(evsel, opts, param);
8518c2ecf20Sopenharmony_ci}
8528c2ecf20Sopenharmony_ci
8538c2ecf20Sopenharmony_cistatic void
8548c2ecf20Sopenharmony_ciperf_evsel__reset_callgraph(struct evsel *evsel,
8558c2ecf20Sopenharmony_ci			    struct callchain_param *param)
8568c2ecf20Sopenharmony_ci{
8578c2ecf20Sopenharmony_ci	struct perf_event_attr *attr = &evsel->core.attr;
8588c2ecf20Sopenharmony_ci
8598c2ecf20Sopenharmony_ci	evsel__reset_sample_bit(evsel, CALLCHAIN);
8608c2ecf20Sopenharmony_ci	if (param->record_mode == CALLCHAIN_LBR) {
8618c2ecf20Sopenharmony_ci		evsel__reset_sample_bit(evsel, BRANCH_STACK);
8628c2ecf20Sopenharmony_ci		attr->branch_sample_type &= ~(PERF_SAMPLE_BRANCH_USER |
8638c2ecf20Sopenharmony_ci					      PERF_SAMPLE_BRANCH_CALL_STACK |
8648c2ecf20Sopenharmony_ci					      PERF_SAMPLE_BRANCH_HW_INDEX);
8658c2ecf20Sopenharmony_ci	}
8668c2ecf20Sopenharmony_ci	if (param->record_mode == CALLCHAIN_DWARF) {
8678c2ecf20Sopenharmony_ci		evsel__reset_sample_bit(evsel, REGS_USER);
8688c2ecf20Sopenharmony_ci		evsel__reset_sample_bit(evsel, STACK_USER);
8698c2ecf20Sopenharmony_ci	}
8708c2ecf20Sopenharmony_ci}
8718c2ecf20Sopenharmony_ci
8728c2ecf20Sopenharmony_cistatic void evsel__apply_config_terms(struct evsel *evsel,
8738c2ecf20Sopenharmony_ci				      struct record_opts *opts, bool track)
8748c2ecf20Sopenharmony_ci{
8758c2ecf20Sopenharmony_ci	struct evsel_config_term *term;
8768c2ecf20Sopenharmony_ci	struct list_head *config_terms = &evsel->config_terms;
8778c2ecf20Sopenharmony_ci	struct perf_event_attr *attr = &evsel->core.attr;
8788c2ecf20Sopenharmony_ci	/* callgraph default */
8798c2ecf20Sopenharmony_ci	struct callchain_param param = {
8808c2ecf20Sopenharmony_ci		.record_mode = callchain_param.record_mode,
8818c2ecf20Sopenharmony_ci	};
8828c2ecf20Sopenharmony_ci	u32 dump_size = 0;
8838c2ecf20Sopenharmony_ci	int max_stack = 0;
8848c2ecf20Sopenharmony_ci	const char *callgraph_buf = NULL;
8858c2ecf20Sopenharmony_ci
8868c2ecf20Sopenharmony_ci	list_for_each_entry(term, config_terms, list) {
8878c2ecf20Sopenharmony_ci		switch (term->type) {
8888c2ecf20Sopenharmony_ci		case EVSEL__CONFIG_TERM_PERIOD:
8898c2ecf20Sopenharmony_ci			if (!(term->weak && opts->user_interval != ULLONG_MAX)) {
8908c2ecf20Sopenharmony_ci				attr->sample_period = term->val.period;
8918c2ecf20Sopenharmony_ci				attr->freq = 0;
8928c2ecf20Sopenharmony_ci				evsel__reset_sample_bit(evsel, PERIOD);
8938c2ecf20Sopenharmony_ci			}
8948c2ecf20Sopenharmony_ci			break;
8958c2ecf20Sopenharmony_ci		case EVSEL__CONFIG_TERM_FREQ:
8968c2ecf20Sopenharmony_ci			if (!(term->weak && opts->user_freq != UINT_MAX)) {
8978c2ecf20Sopenharmony_ci				attr->sample_freq = term->val.freq;
8988c2ecf20Sopenharmony_ci				attr->freq = 1;
8998c2ecf20Sopenharmony_ci				evsel__set_sample_bit(evsel, PERIOD);
9008c2ecf20Sopenharmony_ci			}
9018c2ecf20Sopenharmony_ci			break;
9028c2ecf20Sopenharmony_ci		case EVSEL__CONFIG_TERM_TIME:
9038c2ecf20Sopenharmony_ci			if (term->val.time)
9048c2ecf20Sopenharmony_ci				evsel__set_sample_bit(evsel, TIME);
9058c2ecf20Sopenharmony_ci			else
9068c2ecf20Sopenharmony_ci				evsel__reset_sample_bit(evsel, TIME);
9078c2ecf20Sopenharmony_ci			break;
9088c2ecf20Sopenharmony_ci		case EVSEL__CONFIG_TERM_CALLGRAPH:
9098c2ecf20Sopenharmony_ci			callgraph_buf = term->val.str;
9108c2ecf20Sopenharmony_ci			break;
9118c2ecf20Sopenharmony_ci		case EVSEL__CONFIG_TERM_BRANCH:
9128c2ecf20Sopenharmony_ci			if (term->val.str && strcmp(term->val.str, "no")) {
9138c2ecf20Sopenharmony_ci				evsel__set_sample_bit(evsel, BRANCH_STACK);
9148c2ecf20Sopenharmony_ci				parse_branch_str(term->val.str,
9158c2ecf20Sopenharmony_ci						 &attr->branch_sample_type);
9168c2ecf20Sopenharmony_ci			} else
9178c2ecf20Sopenharmony_ci				evsel__reset_sample_bit(evsel, BRANCH_STACK);
9188c2ecf20Sopenharmony_ci			break;
9198c2ecf20Sopenharmony_ci		case EVSEL__CONFIG_TERM_STACK_USER:
9208c2ecf20Sopenharmony_ci			dump_size = term->val.stack_user;
9218c2ecf20Sopenharmony_ci			break;
9228c2ecf20Sopenharmony_ci		case EVSEL__CONFIG_TERM_MAX_STACK:
9238c2ecf20Sopenharmony_ci			max_stack = term->val.max_stack;
9248c2ecf20Sopenharmony_ci			break;
9258c2ecf20Sopenharmony_ci		case EVSEL__CONFIG_TERM_MAX_EVENTS:
9268c2ecf20Sopenharmony_ci			evsel->max_events = term->val.max_events;
9278c2ecf20Sopenharmony_ci			break;
9288c2ecf20Sopenharmony_ci		case EVSEL__CONFIG_TERM_INHERIT:
9298c2ecf20Sopenharmony_ci			/*
9308c2ecf20Sopenharmony_ci			 * attr->inherit should has already been set by
9318c2ecf20Sopenharmony_ci			 * evsel__config. If user explicitly set
9328c2ecf20Sopenharmony_ci			 * inherit using config terms, override global
9338c2ecf20Sopenharmony_ci			 * opt->no_inherit setting.
9348c2ecf20Sopenharmony_ci			 */
9358c2ecf20Sopenharmony_ci			attr->inherit = term->val.inherit ? 1 : 0;
9368c2ecf20Sopenharmony_ci			break;
9378c2ecf20Sopenharmony_ci		case EVSEL__CONFIG_TERM_OVERWRITE:
9388c2ecf20Sopenharmony_ci			attr->write_backward = term->val.overwrite ? 1 : 0;
9398c2ecf20Sopenharmony_ci			break;
9408c2ecf20Sopenharmony_ci		case EVSEL__CONFIG_TERM_DRV_CFG:
9418c2ecf20Sopenharmony_ci			break;
9428c2ecf20Sopenharmony_ci		case EVSEL__CONFIG_TERM_PERCORE:
9438c2ecf20Sopenharmony_ci			break;
9448c2ecf20Sopenharmony_ci		case EVSEL__CONFIG_TERM_AUX_OUTPUT:
9458c2ecf20Sopenharmony_ci			attr->aux_output = term->val.aux_output ? 1 : 0;
9468c2ecf20Sopenharmony_ci			break;
9478c2ecf20Sopenharmony_ci		case EVSEL__CONFIG_TERM_AUX_SAMPLE_SIZE:
9488c2ecf20Sopenharmony_ci			/* Already applied by auxtrace */
9498c2ecf20Sopenharmony_ci			break;
9508c2ecf20Sopenharmony_ci		case EVSEL__CONFIG_TERM_CFG_CHG:
9518c2ecf20Sopenharmony_ci			break;
9528c2ecf20Sopenharmony_ci		default:
9538c2ecf20Sopenharmony_ci			break;
9548c2ecf20Sopenharmony_ci		}
9558c2ecf20Sopenharmony_ci	}
9568c2ecf20Sopenharmony_ci
9578c2ecf20Sopenharmony_ci	/* User explicitly set per-event callgraph, clear the old setting and reset. */
9588c2ecf20Sopenharmony_ci	if ((callgraph_buf != NULL) || (dump_size > 0) || max_stack) {
9598c2ecf20Sopenharmony_ci		bool sample_address = false;
9608c2ecf20Sopenharmony_ci
9618c2ecf20Sopenharmony_ci		if (max_stack) {
9628c2ecf20Sopenharmony_ci			param.max_stack = max_stack;
9638c2ecf20Sopenharmony_ci			if (callgraph_buf == NULL)
9648c2ecf20Sopenharmony_ci				callgraph_buf = "fp";
9658c2ecf20Sopenharmony_ci		}
9668c2ecf20Sopenharmony_ci
9678c2ecf20Sopenharmony_ci		/* parse callgraph parameters */
9688c2ecf20Sopenharmony_ci		if (callgraph_buf != NULL) {
9698c2ecf20Sopenharmony_ci			if (!strcmp(callgraph_buf, "no")) {
9708c2ecf20Sopenharmony_ci				param.enabled = false;
9718c2ecf20Sopenharmony_ci				param.record_mode = CALLCHAIN_NONE;
9728c2ecf20Sopenharmony_ci			} else {
9738c2ecf20Sopenharmony_ci				param.enabled = true;
9748c2ecf20Sopenharmony_ci				if (parse_callchain_record(callgraph_buf, &param)) {
9758c2ecf20Sopenharmony_ci					pr_err("per-event callgraph setting for %s failed. "
9768c2ecf20Sopenharmony_ci					       "Apply callgraph global setting for it\n",
9778c2ecf20Sopenharmony_ci					       evsel->name);
9788c2ecf20Sopenharmony_ci					return;
9798c2ecf20Sopenharmony_ci				}
9808c2ecf20Sopenharmony_ci				if (param.record_mode == CALLCHAIN_DWARF)
9818c2ecf20Sopenharmony_ci					sample_address = true;
9828c2ecf20Sopenharmony_ci			}
9838c2ecf20Sopenharmony_ci		}
9848c2ecf20Sopenharmony_ci		if (dump_size > 0) {
9858c2ecf20Sopenharmony_ci			dump_size = round_up(dump_size, sizeof(u64));
9868c2ecf20Sopenharmony_ci			param.dump_size = dump_size;
9878c2ecf20Sopenharmony_ci		}
9888c2ecf20Sopenharmony_ci
9898c2ecf20Sopenharmony_ci		/* If global callgraph set, clear it */
9908c2ecf20Sopenharmony_ci		if (callchain_param.enabled)
9918c2ecf20Sopenharmony_ci			perf_evsel__reset_callgraph(evsel, &callchain_param);
9928c2ecf20Sopenharmony_ci
9938c2ecf20Sopenharmony_ci		/* set perf-event callgraph */
9948c2ecf20Sopenharmony_ci		if (param.enabled) {
9958c2ecf20Sopenharmony_ci			if (sample_address) {
9968c2ecf20Sopenharmony_ci				evsel__set_sample_bit(evsel, ADDR);
9978c2ecf20Sopenharmony_ci				evsel__set_sample_bit(evsel, DATA_SRC);
9988c2ecf20Sopenharmony_ci				evsel->core.attr.mmap_data = track;
9998c2ecf20Sopenharmony_ci			}
10008c2ecf20Sopenharmony_ci			evsel__config_callchain(evsel, opts, &param);
10018c2ecf20Sopenharmony_ci		}
10028c2ecf20Sopenharmony_ci	}
10038c2ecf20Sopenharmony_ci}
10048c2ecf20Sopenharmony_ci
10058c2ecf20Sopenharmony_cistruct evsel_config_term *__evsel__get_config_term(struct evsel *evsel, enum evsel_term_type type)
10068c2ecf20Sopenharmony_ci{
10078c2ecf20Sopenharmony_ci	struct evsel_config_term *term, *found_term = NULL;
10088c2ecf20Sopenharmony_ci
10098c2ecf20Sopenharmony_ci	list_for_each_entry(term, &evsel->config_terms, list) {
10108c2ecf20Sopenharmony_ci		if (term->type == type)
10118c2ecf20Sopenharmony_ci			found_term = term;
10128c2ecf20Sopenharmony_ci	}
10138c2ecf20Sopenharmony_ci
10148c2ecf20Sopenharmony_ci	return found_term;
10158c2ecf20Sopenharmony_ci}
10168c2ecf20Sopenharmony_ci
10178c2ecf20Sopenharmony_cistatic void evsel__set_default_freq_period(struct record_opts *opts,
10188c2ecf20Sopenharmony_ci					   struct perf_event_attr *attr)
10198c2ecf20Sopenharmony_ci{
10208c2ecf20Sopenharmony_ci	if (opts->freq) {
10218c2ecf20Sopenharmony_ci		attr->freq = 1;
10228c2ecf20Sopenharmony_ci		attr->sample_freq = opts->freq;
10238c2ecf20Sopenharmony_ci	} else {
10248c2ecf20Sopenharmony_ci		attr->sample_period = opts->default_interval;
10258c2ecf20Sopenharmony_ci	}
10268c2ecf20Sopenharmony_ci}
10278c2ecf20Sopenharmony_ci
10288c2ecf20Sopenharmony_ci/*
10298c2ecf20Sopenharmony_ci * The enable_on_exec/disabled value strategy:
10308c2ecf20Sopenharmony_ci *
10318c2ecf20Sopenharmony_ci *  1) For any type of traced program:
10328c2ecf20Sopenharmony_ci *    - all independent events and group leaders are disabled
10338c2ecf20Sopenharmony_ci *    - all group members are enabled
10348c2ecf20Sopenharmony_ci *
10358c2ecf20Sopenharmony_ci *     Group members are ruled by group leaders. They need to
10368c2ecf20Sopenharmony_ci *     be enabled, because the group scheduling relies on that.
10378c2ecf20Sopenharmony_ci *
10388c2ecf20Sopenharmony_ci *  2) For traced programs executed by perf:
10398c2ecf20Sopenharmony_ci *     - all independent events and group leaders have
10408c2ecf20Sopenharmony_ci *       enable_on_exec set
10418c2ecf20Sopenharmony_ci *     - we don't specifically enable or disable any event during
10428c2ecf20Sopenharmony_ci *       the record command
10438c2ecf20Sopenharmony_ci *
10448c2ecf20Sopenharmony_ci *     Independent events and group leaders are initially disabled
10458c2ecf20Sopenharmony_ci *     and get enabled by exec. Group members are ruled by group
10468c2ecf20Sopenharmony_ci *     leaders as stated in 1).
10478c2ecf20Sopenharmony_ci *
10488c2ecf20Sopenharmony_ci *  3) For traced programs attached by perf (pid/tid):
10498c2ecf20Sopenharmony_ci *     - we specifically enable or disable all events during
10508c2ecf20Sopenharmony_ci *       the record command
10518c2ecf20Sopenharmony_ci *
10528c2ecf20Sopenharmony_ci *     When attaching events to already running traced we
10538c2ecf20Sopenharmony_ci *     enable/disable events specifically, as there's no
10548c2ecf20Sopenharmony_ci *     initial traced exec call.
10558c2ecf20Sopenharmony_ci */
10568c2ecf20Sopenharmony_civoid evsel__config(struct evsel *evsel, struct record_opts *opts,
10578c2ecf20Sopenharmony_ci		   struct callchain_param *callchain)
10588c2ecf20Sopenharmony_ci{
10598c2ecf20Sopenharmony_ci	struct evsel *leader = evsel->leader;
10608c2ecf20Sopenharmony_ci	struct perf_event_attr *attr = &evsel->core.attr;
10618c2ecf20Sopenharmony_ci	int track = evsel->tracking;
10628c2ecf20Sopenharmony_ci	bool per_cpu = opts->target.default_per_cpu && !opts->target.per_thread;
10638c2ecf20Sopenharmony_ci
10648c2ecf20Sopenharmony_ci	attr->sample_id_all = perf_missing_features.sample_id_all ? 0 : 1;
10658c2ecf20Sopenharmony_ci	attr->inherit	    = !opts->no_inherit;
10668c2ecf20Sopenharmony_ci	attr->write_backward = opts->overwrite ? 1 : 0;
10678c2ecf20Sopenharmony_ci
10688c2ecf20Sopenharmony_ci	evsel__set_sample_bit(evsel, IP);
10698c2ecf20Sopenharmony_ci	evsel__set_sample_bit(evsel, TID);
10708c2ecf20Sopenharmony_ci
10718c2ecf20Sopenharmony_ci	if (evsel->sample_read) {
10728c2ecf20Sopenharmony_ci		evsel__set_sample_bit(evsel, READ);
10738c2ecf20Sopenharmony_ci
10748c2ecf20Sopenharmony_ci		/*
10758c2ecf20Sopenharmony_ci		 * We need ID even in case of single event, because
10768c2ecf20Sopenharmony_ci		 * PERF_SAMPLE_READ process ID specific data.
10778c2ecf20Sopenharmony_ci		 */
10788c2ecf20Sopenharmony_ci		evsel__set_sample_id(evsel, false);
10798c2ecf20Sopenharmony_ci
10808c2ecf20Sopenharmony_ci		/*
10818c2ecf20Sopenharmony_ci		 * Apply group format only if we belong to group
10828c2ecf20Sopenharmony_ci		 * with more than one members.
10838c2ecf20Sopenharmony_ci		 */
10848c2ecf20Sopenharmony_ci		if (leader->core.nr_members > 1) {
10858c2ecf20Sopenharmony_ci			attr->read_format |= PERF_FORMAT_GROUP;
10868c2ecf20Sopenharmony_ci			attr->inherit = 0;
10878c2ecf20Sopenharmony_ci		}
10888c2ecf20Sopenharmony_ci	}
10898c2ecf20Sopenharmony_ci
10908c2ecf20Sopenharmony_ci	/*
10918c2ecf20Sopenharmony_ci	 * We default some events to have a default interval. But keep
10928c2ecf20Sopenharmony_ci	 * it a weak assumption overridable by the user.
10938c2ecf20Sopenharmony_ci	 */
10948c2ecf20Sopenharmony_ci	if ((evsel->is_libpfm_event && !attr->sample_period) ||
10958c2ecf20Sopenharmony_ci	    (!evsel->is_libpfm_event && (!attr->sample_period ||
10968c2ecf20Sopenharmony_ci					 opts->user_freq != UINT_MAX ||
10978c2ecf20Sopenharmony_ci					 opts->user_interval != ULLONG_MAX)))
10988c2ecf20Sopenharmony_ci		evsel__set_default_freq_period(opts, attr);
10998c2ecf20Sopenharmony_ci
11008c2ecf20Sopenharmony_ci	/*
11018c2ecf20Sopenharmony_ci	 * If attr->freq was set (here or earlier), ask for period
11028c2ecf20Sopenharmony_ci	 * to be sampled.
11038c2ecf20Sopenharmony_ci	 */
11048c2ecf20Sopenharmony_ci	if (attr->freq)
11058c2ecf20Sopenharmony_ci		evsel__set_sample_bit(evsel, PERIOD);
11068c2ecf20Sopenharmony_ci
11078c2ecf20Sopenharmony_ci	if (opts->no_samples)
11088c2ecf20Sopenharmony_ci		attr->sample_freq = 0;
11098c2ecf20Sopenharmony_ci
11108c2ecf20Sopenharmony_ci	if (opts->inherit_stat) {
11118c2ecf20Sopenharmony_ci		evsel->core.attr.read_format |=
11128c2ecf20Sopenharmony_ci			PERF_FORMAT_TOTAL_TIME_ENABLED |
11138c2ecf20Sopenharmony_ci			PERF_FORMAT_TOTAL_TIME_RUNNING |
11148c2ecf20Sopenharmony_ci			PERF_FORMAT_ID;
11158c2ecf20Sopenharmony_ci		attr->inherit_stat = 1;
11168c2ecf20Sopenharmony_ci	}
11178c2ecf20Sopenharmony_ci
11188c2ecf20Sopenharmony_ci	if (opts->sample_address) {
11198c2ecf20Sopenharmony_ci		evsel__set_sample_bit(evsel, ADDR);
11208c2ecf20Sopenharmony_ci		attr->mmap_data = track;
11218c2ecf20Sopenharmony_ci	}
11228c2ecf20Sopenharmony_ci
11238c2ecf20Sopenharmony_ci	/*
11248c2ecf20Sopenharmony_ci	 * We don't allow user space callchains for  function trace
11258c2ecf20Sopenharmony_ci	 * event, due to issues with page faults while tracing page
11268c2ecf20Sopenharmony_ci	 * fault handler and its overall trickiness nature.
11278c2ecf20Sopenharmony_ci	 */
11288c2ecf20Sopenharmony_ci	if (evsel__is_function_event(evsel))
11298c2ecf20Sopenharmony_ci		evsel->core.attr.exclude_callchain_user = 1;
11308c2ecf20Sopenharmony_ci
11318c2ecf20Sopenharmony_ci	if (callchain && callchain->enabled && !evsel->no_aux_samples)
11328c2ecf20Sopenharmony_ci		evsel__config_callchain(evsel, opts, callchain);
11338c2ecf20Sopenharmony_ci
11348c2ecf20Sopenharmony_ci	if (opts->sample_intr_regs && !evsel->no_aux_samples &&
11358c2ecf20Sopenharmony_ci	    !evsel__is_dummy_event(evsel)) {
11368c2ecf20Sopenharmony_ci		attr->sample_regs_intr = opts->sample_intr_regs;
11378c2ecf20Sopenharmony_ci		evsel__set_sample_bit(evsel, REGS_INTR);
11388c2ecf20Sopenharmony_ci	}
11398c2ecf20Sopenharmony_ci
11408c2ecf20Sopenharmony_ci	if (opts->sample_user_regs && !evsel->no_aux_samples &&
11418c2ecf20Sopenharmony_ci	    !evsel__is_dummy_event(evsel)) {
11428c2ecf20Sopenharmony_ci		attr->sample_regs_user |= opts->sample_user_regs;
11438c2ecf20Sopenharmony_ci		evsel__set_sample_bit(evsel, REGS_USER);
11448c2ecf20Sopenharmony_ci	}
11458c2ecf20Sopenharmony_ci
11468c2ecf20Sopenharmony_ci	if (target__has_cpu(&opts->target) || opts->sample_cpu)
11478c2ecf20Sopenharmony_ci		evsel__set_sample_bit(evsel, CPU);
11488c2ecf20Sopenharmony_ci
11498c2ecf20Sopenharmony_ci	/*
11508c2ecf20Sopenharmony_ci	 * When the user explicitly disabled time don't force it here.
11518c2ecf20Sopenharmony_ci	 */
11528c2ecf20Sopenharmony_ci	if (opts->sample_time &&
11538c2ecf20Sopenharmony_ci	    (!perf_missing_features.sample_id_all &&
11548c2ecf20Sopenharmony_ci	    (!opts->no_inherit || target__has_cpu(&opts->target) || per_cpu ||
11558c2ecf20Sopenharmony_ci	     opts->sample_time_set)))
11568c2ecf20Sopenharmony_ci		evsel__set_sample_bit(evsel, TIME);
11578c2ecf20Sopenharmony_ci
11588c2ecf20Sopenharmony_ci	if (opts->raw_samples && !evsel->no_aux_samples) {
11598c2ecf20Sopenharmony_ci		evsel__set_sample_bit(evsel, TIME);
11608c2ecf20Sopenharmony_ci		evsel__set_sample_bit(evsel, RAW);
11618c2ecf20Sopenharmony_ci		evsel__set_sample_bit(evsel, CPU);
11628c2ecf20Sopenharmony_ci	}
11638c2ecf20Sopenharmony_ci
11648c2ecf20Sopenharmony_ci	if (opts->sample_address)
11658c2ecf20Sopenharmony_ci		evsel__set_sample_bit(evsel, DATA_SRC);
11668c2ecf20Sopenharmony_ci
11678c2ecf20Sopenharmony_ci	if (opts->sample_phys_addr)
11688c2ecf20Sopenharmony_ci		evsel__set_sample_bit(evsel, PHYS_ADDR);
11698c2ecf20Sopenharmony_ci
11708c2ecf20Sopenharmony_ci	if (opts->no_buffering) {
11718c2ecf20Sopenharmony_ci		attr->watermark = 0;
11728c2ecf20Sopenharmony_ci		attr->wakeup_events = 1;
11738c2ecf20Sopenharmony_ci	}
11748c2ecf20Sopenharmony_ci	if (opts->branch_stack && !evsel->no_aux_samples) {
11758c2ecf20Sopenharmony_ci		evsel__set_sample_bit(evsel, BRANCH_STACK);
11768c2ecf20Sopenharmony_ci		attr->branch_sample_type = opts->branch_stack;
11778c2ecf20Sopenharmony_ci	}
11788c2ecf20Sopenharmony_ci
11798c2ecf20Sopenharmony_ci	if (opts->sample_weight)
11808c2ecf20Sopenharmony_ci		evsel__set_sample_bit(evsel, WEIGHT);
11818c2ecf20Sopenharmony_ci
11828c2ecf20Sopenharmony_ci	attr->task  = track;
11838c2ecf20Sopenharmony_ci	attr->mmap  = track;
11848c2ecf20Sopenharmony_ci	attr->mmap2 = track && !perf_missing_features.mmap2;
11858c2ecf20Sopenharmony_ci	attr->comm  = track;
11868c2ecf20Sopenharmony_ci	/*
11878c2ecf20Sopenharmony_ci	 * ksymbol is tracked separately with text poke because it needs to be
11888c2ecf20Sopenharmony_ci	 * system wide and enabled immediately.
11898c2ecf20Sopenharmony_ci	 */
11908c2ecf20Sopenharmony_ci	if (!opts->text_poke)
11918c2ecf20Sopenharmony_ci		attr->ksymbol = track && !perf_missing_features.ksymbol;
11928c2ecf20Sopenharmony_ci	attr->bpf_event = track && !opts->no_bpf_event && !perf_missing_features.bpf;
11938c2ecf20Sopenharmony_ci
11948c2ecf20Sopenharmony_ci	if (opts->record_namespaces)
11958c2ecf20Sopenharmony_ci		attr->namespaces  = track;
11968c2ecf20Sopenharmony_ci
11978c2ecf20Sopenharmony_ci	if (opts->record_cgroup) {
11988c2ecf20Sopenharmony_ci		attr->cgroup = track && !perf_missing_features.cgroup;
11998c2ecf20Sopenharmony_ci		evsel__set_sample_bit(evsel, CGROUP);
12008c2ecf20Sopenharmony_ci	}
12018c2ecf20Sopenharmony_ci
12028c2ecf20Sopenharmony_ci	if (opts->record_switch_events)
12038c2ecf20Sopenharmony_ci		attr->context_switch = track;
12048c2ecf20Sopenharmony_ci
12058c2ecf20Sopenharmony_ci	if (opts->sample_transaction)
12068c2ecf20Sopenharmony_ci		evsel__set_sample_bit(evsel, TRANSACTION);
12078c2ecf20Sopenharmony_ci
12088c2ecf20Sopenharmony_ci	if (opts->running_time) {
12098c2ecf20Sopenharmony_ci		evsel->core.attr.read_format |=
12108c2ecf20Sopenharmony_ci			PERF_FORMAT_TOTAL_TIME_ENABLED |
12118c2ecf20Sopenharmony_ci			PERF_FORMAT_TOTAL_TIME_RUNNING;
12128c2ecf20Sopenharmony_ci	}
12138c2ecf20Sopenharmony_ci
12148c2ecf20Sopenharmony_ci	/*
12158c2ecf20Sopenharmony_ci	 * XXX see the function comment above
12168c2ecf20Sopenharmony_ci	 *
12178c2ecf20Sopenharmony_ci	 * Disabling only independent events or group leaders,
12188c2ecf20Sopenharmony_ci	 * keeping group members enabled.
12198c2ecf20Sopenharmony_ci	 */
12208c2ecf20Sopenharmony_ci	if (evsel__is_group_leader(evsel))
12218c2ecf20Sopenharmony_ci		attr->disabled = 1;
12228c2ecf20Sopenharmony_ci
12238c2ecf20Sopenharmony_ci	/*
12248c2ecf20Sopenharmony_ci	 * Setting enable_on_exec for independent events and
12258c2ecf20Sopenharmony_ci	 * group leaders for traced executed by perf.
12268c2ecf20Sopenharmony_ci	 */
12278c2ecf20Sopenharmony_ci	if (target__none(&opts->target) && evsel__is_group_leader(evsel) &&
12288c2ecf20Sopenharmony_ci	    !opts->initial_delay)
12298c2ecf20Sopenharmony_ci		attr->enable_on_exec = 1;
12308c2ecf20Sopenharmony_ci
12318c2ecf20Sopenharmony_ci	if (evsel->immediate) {
12328c2ecf20Sopenharmony_ci		attr->disabled = 0;
12338c2ecf20Sopenharmony_ci		attr->enable_on_exec = 0;
12348c2ecf20Sopenharmony_ci	}
12358c2ecf20Sopenharmony_ci
12368c2ecf20Sopenharmony_ci	clockid = opts->clockid;
12378c2ecf20Sopenharmony_ci	if (opts->use_clockid) {
12388c2ecf20Sopenharmony_ci		attr->use_clockid = 1;
12398c2ecf20Sopenharmony_ci		attr->clockid = opts->clockid;
12408c2ecf20Sopenharmony_ci	}
12418c2ecf20Sopenharmony_ci
12428c2ecf20Sopenharmony_ci	if (evsel->precise_max)
12438c2ecf20Sopenharmony_ci		attr->precise_ip = 3;
12448c2ecf20Sopenharmony_ci
12458c2ecf20Sopenharmony_ci	if (opts->all_user) {
12468c2ecf20Sopenharmony_ci		attr->exclude_kernel = 1;
12478c2ecf20Sopenharmony_ci		attr->exclude_user   = 0;
12488c2ecf20Sopenharmony_ci	}
12498c2ecf20Sopenharmony_ci
12508c2ecf20Sopenharmony_ci	if (opts->all_kernel) {
12518c2ecf20Sopenharmony_ci		attr->exclude_kernel = 0;
12528c2ecf20Sopenharmony_ci		attr->exclude_user   = 1;
12538c2ecf20Sopenharmony_ci	}
12548c2ecf20Sopenharmony_ci
12558c2ecf20Sopenharmony_ci	if (evsel->core.own_cpus || evsel->unit)
12568c2ecf20Sopenharmony_ci		evsel->core.attr.read_format |= PERF_FORMAT_ID;
12578c2ecf20Sopenharmony_ci
12588c2ecf20Sopenharmony_ci	/*
12598c2ecf20Sopenharmony_ci	 * Apply event specific term settings,
12608c2ecf20Sopenharmony_ci	 * it overloads any global configuration.
12618c2ecf20Sopenharmony_ci	 */
12628c2ecf20Sopenharmony_ci	evsel__apply_config_terms(evsel, opts, track);
12638c2ecf20Sopenharmony_ci
12648c2ecf20Sopenharmony_ci	evsel->ignore_missing_thread = opts->ignore_missing_thread;
12658c2ecf20Sopenharmony_ci
12668c2ecf20Sopenharmony_ci	/* The --period option takes the precedence. */
12678c2ecf20Sopenharmony_ci	if (opts->period_set) {
12688c2ecf20Sopenharmony_ci		if (opts->period)
12698c2ecf20Sopenharmony_ci			evsel__set_sample_bit(evsel, PERIOD);
12708c2ecf20Sopenharmony_ci		else
12718c2ecf20Sopenharmony_ci			evsel__reset_sample_bit(evsel, PERIOD);
12728c2ecf20Sopenharmony_ci	}
12738c2ecf20Sopenharmony_ci
12748c2ecf20Sopenharmony_ci	/*
12758c2ecf20Sopenharmony_ci	 * A dummy event never triggers any actual counter and therefore
12768c2ecf20Sopenharmony_ci	 * cannot be used with branch_stack.
12778c2ecf20Sopenharmony_ci	 *
12788c2ecf20Sopenharmony_ci	 * For initial_delay, a dummy event is added implicitly.
12798c2ecf20Sopenharmony_ci	 * The software event will trigger -EOPNOTSUPP error out,
12808c2ecf20Sopenharmony_ci	 * if BRANCH_STACK bit is set.
12818c2ecf20Sopenharmony_ci	 */
12828c2ecf20Sopenharmony_ci	if (evsel__is_dummy_event(evsel))
12838c2ecf20Sopenharmony_ci		evsel__reset_sample_bit(evsel, BRANCH_STACK);
12848c2ecf20Sopenharmony_ci}
12858c2ecf20Sopenharmony_ci
12868c2ecf20Sopenharmony_ciint evsel__set_filter(struct evsel *evsel, const char *filter)
12878c2ecf20Sopenharmony_ci{
12888c2ecf20Sopenharmony_ci	char *new_filter = strdup(filter);
12898c2ecf20Sopenharmony_ci
12908c2ecf20Sopenharmony_ci	if (new_filter != NULL) {
12918c2ecf20Sopenharmony_ci		free(evsel->filter);
12928c2ecf20Sopenharmony_ci		evsel->filter = new_filter;
12938c2ecf20Sopenharmony_ci		return 0;
12948c2ecf20Sopenharmony_ci	}
12958c2ecf20Sopenharmony_ci
12968c2ecf20Sopenharmony_ci	return -1;
12978c2ecf20Sopenharmony_ci}
12988c2ecf20Sopenharmony_ci
12998c2ecf20Sopenharmony_cistatic int evsel__append_filter(struct evsel *evsel, const char *fmt, const char *filter)
13008c2ecf20Sopenharmony_ci{
13018c2ecf20Sopenharmony_ci	char *new_filter;
13028c2ecf20Sopenharmony_ci
13038c2ecf20Sopenharmony_ci	if (evsel->filter == NULL)
13048c2ecf20Sopenharmony_ci		return evsel__set_filter(evsel, filter);
13058c2ecf20Sopenharmony_ci
13068c2ecf20Sopenharmony_ci	if (asprintf(&new_filter, fmt, evsel->filter, filter) > 0) {
13078c2ecf20Sopenharmony_ci		free(evsel->filter);
13088c2ecf20Sopenharmony_ci		evsel->filter = new_filter;
13098c2ecf20Sopenharmony_ci		return 0;
13108c2ecf20Sopenharmony_ci	}
13118c2ecf20Sopenharmony_ci
13128c2ecf20Sopenharmony_ci	return -1;
13138c2ecf20Sopenharmony_ci}
13148c2ecf20Sopenharmony_ci
13158c2ecf20Sopenharmony_ciint evsel__append_tp_filter(struct evsel *evsel, const char *filter)
13168c2ecf20Sopenharmony_ci{
13178c2ecf20Sopenharmony_ci	return evsel__append_filter(evsel, "(%s) && (%s)", filter);
13188c2ecf20Sopenharmony_ci}
13198c2ecf20Sopenharmony_ci
13208c2ecf20Sopenharmony_ciint evsel__append_addr_filter(struct evsel *evsel, const char *filter)
13218c2ecf20Sopenharmony_ci{
13228c2ecf20Sopenharmony_ci	return evsel__append_filter(evsel, "%s,%s", filter);
13238c2ecf20Sopenharmony_ci}
13248c2ecf20Sopenharmony_ci
13258c2ecf20Sopenharmony_ci/* Caller has to clear disabled after going through all CPUs. */
13268c2ecf20Sopenharmony_ciint evsel__enable_cpu(struct evsel *evsel, int cpu)
13278c2ecf20Sopenharmony_ci{
13288c2ecf20Sopenharmony_ci	return perf_evsel__enable_cpu(&evsel->core, cpu);
13298c2ecf20Sopenharmony_ci}
13308c2ecf20Sopenharmony_ci
13318c2ecf20Sopenharmony_ciint evsel__enable(struct evsel *evsel)
13328c2ecf20Sopenharmony_ci{
13338c2ecf20Sopenharmony_ci	int err = perf_evsel__enable(&evsel->core);
13348c2ecf20Sopenharmony_ci
13358c2ecf20Sopenharmony_ci	if (!err)
13368c2ecf20Sopenharmony_ci		evsel->disabled = false;
13378c2ecf20Sopenharmony_ci	return err;
13388c2ecf20Sopenharmony_ci}
13398c2ecf20Sopenharmony_ci
13408c2ecf20Sopenharmony_ci/* Caller has to set disabled after going through all CPUs. */
13418c2ecf20Sopenharmony_ciint evsel__disable_cpu(struct evsel *evsel, int cpu)
13428c2ecf20Sopenharmony_ci{
13438c2ecf20Sopenharmony_ci	return perf_evsel__disable_cpu(&evsel->core, cpu);
13448c2ecf20Sopenharmony_ci}
13458c2ecf20Sopenharmony_ci
13468c2ecf20Sopenharmony_ciint evsel__disable(struct evsel *evsel)
13478c2ecf20Sopenharmony_ci{
13488c2ecf20Sopenharmony_ci	int err = perf_evsel__disable(&evsel->core);
13498c2ecf20Sopenharmony_ci	/*
13508c2ecf20Sopenharmony_ci	 * We mark it disabled here so that tools that disable a event can
13518c2ecf20Sopenharmony_ci	 * ignore events after they disable it. I.e. the ring buffer may have
13528c2ecf20Sopenharmony_ci	 * already a few more events queued up before the kernel got the stop
13538c2ecf20Sopenharmony_ci	 * request.
13548c2ecf20Sopenharmony_ci	 */
13558c2ecf20Sopenharmony_ci	if (!err)
13568c2ecf20Sopenharmony_ci		evsel->disabled = true;
13578c2ecf20Sopenharmony_ci
13588c2ecf20Sopenharmony_ci	return err;
13598c2ecf20Sopenharmony_ci}
13608c2ecf20Sopenharmony_ci
13618c2ecf20Sopenharmony_cistatic void evsel__free_config_terms(struct evsel *evsel)
13628c2ecf20Sopenharmony_ci{
13638c2ecf20Sopenharmony_ci	struct evsel_config_term *term, *h;
13648c2ecf20Sopenharmony_ci
13658c2ecf20Sopenharmony_ci	list_for_each_entry_safe(term, h, &evsel->config_terms, list) {
13668c2ecf20Sopenharmony_ci		list_del_init(&term->list);
13678c2ecf20Sopenharmony_ci		if (term->free_str)
13688c2ecf20Sopenharmony_ci			zfree(&term->val.str);
13698c2ecf20Sopenharmony_ci		free(term);
13708c2ecf20Sopenharmony_ci	}
13718c2ecf20Sopenharmony_ci}
13728c2ecf20Sopenharmony_ci
13738c2ecf20Sopenharmony_civoid evsel__exit(struct evsel *evsel)
13748c2ecf20Sopenharmony_ci{
13758c2ecf20Sopenharmony_ci	assert(list_empty(&evsel->core.node));
13768c2ecf20Sopenharmony_ci	assert(evsel->evlist == NULL);
13778c2ecf20Sopenharmony_ci	evsel__free_counts(evsel);
13788c2ecf20Sopenharmony_ci	perf_evsel__free_fd(&evsel->core);
13798c2ecf20Sopenharmony_ci	perf_evsel__free_id(&evsel->core);
13808c2ecf20Sopenharmony_ci	evsel__free_config_terms(evsel);
13818c2ecf20Sopenharmony_ci	cgroup__put(evsel->cgrp);
13828c2ecf20Sopenharmony_ci	perf_cpu_map__put(evsel->core.cpus);
13838c2ecf20Sopenharmony_ci	perf_cpu_map__put(evsel->core.own_cpus);
13848c2ecf20Sopenharmony_ci	perf_thread_map__put(evsel->core.threads);
13858c2ecf20Sopenharmony_ci	zfree(&evsel->group_name);
13868c2ecf20Sopenharmony_ci	zfree(&evsel->name);
13878c2ecf20Sopenharmony_ci	zfree(&evsel->pmu_name);
13888c2ecf20Sopenharmony_ci	zfree(&evsel->per_pkg_mask);
13898c2ecf20Sopenharmony_ci	zfree(&evsel->metric_events);
13908c2ecf20Sopenharmony_ci	perf_evsel__object.fini(evsel);
13918c2ecf20Sopenharmony_ci}
13928c2ecf20Sopenharmony_ci
13938c2ecf20Sopenharmony_civoid evsel__delete(struct evsel *evsel)
13948c2ecf20Sopenharmony_ci{
13958c2ecf20Sopenharmony_ci	evsel__exit(evsel);
13968c2ecf20Sopenharmony_ci	free(evsel);
13978c2ecf20Sopenharmony_ci}
13988c2ecf20Sopenharmony_ci
13998c2ecf20Sopenharmony_civoid evsel__compute_deltas(struct evsel *evsel, int cpu, int thread,
14008c2ecf20Sopenharmony_ci			   struct perf_counts_values *count)
14018c2ecf20Sopenharmony_ci{
14028c2ecf20Sopenharmony_ci	struct perf_counts_values tmp;
14038c2ecf20Sopenharmony_ci
14048c2ecf20Sopenharmony_ci	if (!evsel->prev_raw_counts)
14058c2ecf20Sopenharmony_ci		return;
14068c2ecf20Sopenharmony_ci
14078c2ecf20Sopenharmony_ci	if (cpu == -1) {
14088c2ecf20Sopenharmony_ci		tmp = evsel->prev_raw_counts->aggr;
14098c2ecf20Sopenharmony_ci		evsel->prev_raw_counts->aggr = *count;
14108c2ecf20Sopenharmony_ci	} else {
14118c2ecf20Sopenharmony_ci		tmp = *perf_counts(evsel->prev_raw_counts, cpu, thread);
14128c2ecf20Sopenharmony_ci		*perf_counts(evsel->prev_raw_counts, cpu, thread) = *count;
14138c2ecf20Sopenharmony_ci	}
14148c2ecf20Sopenharmony_ci
14158c2ecf20Sopenharmony_ci	count->val = count->val - tmp.val;
14168c2ecf20Sopenharmony_ci	count->ena = count->ena - tmp.ena;
14178c2ecf20Sopenharmony_ci	count->run = count->run - tmp.run;
14188c2ecf20Sopenharmony_ci}
14198c2ecf20Sopenharmony_ci
14208c2ecf20Sopenharmony_civoid perf_counts_values__scale(struct perf_counts_values *count,
14218c2ecf20Sopenharmony_ci			       bool scale, s8 *pscaled)
14228c2ecf20Sopenharmony_ci{
14238c2ecf20Sopenharmony_ci	s8 scaled = 0;
14248c2ecf20Sopenharmony_ci
14258c2ecf20Sopenharmony_ci	if (scale) {
14268c2ecf20Sopenharmony_ci		if (count->run == 0) {
14278c2ecf20Sopenharmony_ci			scaled = -1;
14288c2ecf20Sopenharmony_ci			count->val = 0;
14298c2ecf20Sopenharmony_ci		} else if (count->run < count->ena) {
14308c2ecf20Sopenharmony_ci			scaled = 1;
14318c2ecf20Sopenharmony_ci			count->val = (u64)((double) count->val * count->ena / count->run);
14328c2ecf20Sopenharmony_ci		}
14338c2ecf20Sopenharmony_ci	}
14348c2ecf20Sopenharmony_ci
14358c2ecf20Sopenharmony_ci	if (pscaled)
14368c2ecf20Sopenharmony_ci		*pscaled = scaled;
14378c2ecf20Sopenharmony_ci}
14388c2ecf20Sopenharmony_ci
14398c2ecf20Sopenharmony_cistatic int evsel__read_one(struct evsel *evsel, int cpu, int thread)
14408c2ecf20Sopenharmony_ci{
14418c2ecf20Sopenharmony_ci	struct perf_counts_values *count = perf_counts(evsel->counts, cpu, thread);
14428c2ecf20Sopenharmony_ci
14438c2ecf20Sopenharmony_ci	return perf_evsel__read(&evsel->core, cpu, thread, count);
14448c2ecf20Sopenharmony_ci}
14458c2ecf20Sopenharmony_ci
14468c2ecf20Sopenharmony_cistatic void
14478c2ecf20Sopenharmony_ciperf_evsel__set_count(struct evsel *counter, int cpu, int thread,
14488c2ecf20Sopenharmony_ci		      u64 val, u64 ena, u64 run)
14498c2ecf20Sopenharmony_ci{
14508c2ecf20Sopenharmony_ci	struct perf_counts_values *count;
14518c2ecf20Sopenharmony_ci
14528c2ecf20Sopenharmony_ci	count = perf_counts(counter->counts, cpu, thread);
14538c2ecf20Sopenharmony_ci
14548c2ecf20Sopenharmony_ci	count->val    = val;
14558c2ecf20Sopenharmony_ci	count->ena    = ena;
14568c2ecf20Sopenharmony_ci	count->run    = run;
14578c2ecf20Sopenharmony_ci
14588c2ecf20Sopenharmony_ci	perf_counts__set_loaded(counter->counts, cpu, thread, true);
14598c2ecf20Sopenharmony_ci}
14608c2ecf20Sopenharmony_ci
14618c2ecf20Sopenharmony_cistatic int
14628c2ecf20Sopenharmony_ciperf_evsel__process_group_data(struct evsel *leader,
14638c2ecf20Sopenharmony_ci			       int cpu, int thread, u64 *data)
14648c2ecf20Sopenharmony_ci{
14658c2ecf20Sopenharmony_ci	u64 read_format = leader->core.attr.read_format;
14668c2ecf20Sopenharmony_ci	struct sample_read_value *v;
14678c2ecf20Sopenharmony_ci	u64 nr, ena = 0, run = 0, i;
14688c2ecf20Sopenharmony_ci
14698c2ecf20Sopenharmony_ci	nr = *data++;
14708c2ecf20Sopenharmony_ci
14718c2ecf20Sopenharmony_ci	if (nr != (u64) leader->core.nr_members)
14728c2ecf20Sopenharmony_ci		return -EINVAL;
14738c2ecf20Sopenharmony_ci
14748c2ecf20Sopenharmony_ci	if (read_format & PERF_FORMAT_TOTAL_TIME_ENABLED)
14758c2ecf20Sopenharmony_ci		ena = *data++;
14768c2ecf20Sopenharmony_ci
14778c2ecf20Sopenharmony_ci	if (read_format & PERF_FORMAT_TOTAL_TIME_RUNNING)
14788c2ecf20Sopenharmony_ci		run = *data++;
14798c2ecf20Sopenharmony_ci
14808c2ecf20Sopenharmony_ci	v = (struct sample_read_value *) data;
14818c2ecf20Sopenharmony_ci
14828c2ecf20Sopenharmony_ci	perf_evsel__set_count(leader, cpu, thread,
14838c2ecf20Sopenharmony_ci			      v[0].value, ena, run);
14848c2ecf20Sopenharmony_ci
14858c2ecf20Sopenharmony_ci	for (i = 1; i < nr; i++) {
14868c2ecf20Sopenharmony_ci		struct evsel *counter;
14878c2ecf20Sopenharmony_ci
14888c2ecf20Sopenharmony_ci		counter = perf_evlist__id2evsel(leader->evlist, v[i].id);
14898c2ecf20Sopenharmony_ci		if (!counter)
14908c2ecf20Sopenharmony_ci			return -EINVAL;
14918c2ecf20Sopenharmony_ci
14928c2ecf20Sopenharmony_ci		perf_evsel__set_count(counter, cpu, thread,
14938c2ecf20Sopenharmony_ci				      v[i].value, ena, run);
14948c2ecf20Sopenharmony_ci	}
14958c2ecf20Sopenharmony_ci
14968c2ecf20Sopenharmony_ci	return 0;
14978c2ecf20Sopenharmony_ci}
14988c2ecf20Sopenharmony_ci
14998c2ecf20Sopenharmony_cistatic int evsel__read_group(struct evsel *leader, int cpu, int thread)
15008c2ecf20Sopenharmony_ci{
15018c2ecf20Sopenharmony_ci	struct perf_stat_evsel *ps = leader->stats;
15028c2ecf20Sopenharmony_ci	u64 read_format = leader->core.attr.read_format;
15038c2ecf20Sopenharmony_ci	int size = perf_evsel__read_size(&leader->core);
15048c2ecf20Sopenharmony_ci	u64 *data = ps->group_data;
15058c2ecf20Sopenharmony_ci
15068c2ecf20Sopenharmony_ci	if (!(read_format & PERF_FORMAT_ID))
15078c2ecf20Sopenharmony_ci		return -EINVAL;
15088c2ecf20Sopenharmony_ci
15098c2ecf20Sopenharmony_ci	if (!evsel__is_group_leader(leader))
15108c2ecf20Sopenharmony_ci		return -EINVAL;
15118c2ecf20Sopenharmony_ci
15128c2ecf20Sopenharmony_ci	if (!data) {
15138c2ecf20Sopenharmony_ci		data = zalloc(size);
15148c2ecf20Sopenharmony_ci		if (!data)
15158c2ecf20Sopenharmony_ci			return -ENOMEM;
15168c2ecf20Sopenharmony_ci
15178c2ecf20Sopenharmony_ci		ps->group_data = data;
15188c2ecf20Sopenharmony_ci	}
15198c2ecf20Sopenharmony_ci
15208c2ecf20Sopenharmony_ci	if (FD(leader, cpu, thread) < 0)
15218c2ecf20Sopenharmony_ci		return -EINVAL;
15228c2ecf20Sopenharmony_ci
15238c2ecf20Sopenharmony_ci	if (readn(FD(leader, cpu, thread), data, size) <= 0)
15248c2ecf20Sopenharmony_ci		return -errno;
15258c2ecf20Sopenharmony_ci
15268c2ecf20Sopenharmony_ci	return perf_evsel__process_group_data(leader, cpu, thread, data);
15278c2ecf20Sopenharmony_ci}
15288c2ecf20Sopenharmony_ci
15298c2ecf20Sopenharmony_ciint evsel__read_counter(struct evsel *evsel, int cpu, int thread)
15308c2ecf20Sopenharmony_ci{
15318c2ecf20Sopenharmony_ci	u64 read_format = evsel->core.attr.read_format;
15328c2ecf20Sopenharmony_ci
15338c2ecf20Sopenharmony_ci	if (read_format & PERF_FORMAT_GROUP)
15348c2ecf20Sopenharmony_ci		return evsel__read_group(evsel, cpu, thread);
15358c2ecf20Sopenharmony_ci
15368c2ecf20Sopenharmony_ci	return evsel__read_one(evsel, cpu, thread);
15378c2ecf20Sopenharmony_ci}
15388c2ecf20Sopenharmony_ci
15398c2ecf20Sopenharmony_ciint __evsel__read_on_cpu(struct evsel *evsel, int cpu, int thread, bool scale)
15408c2ecf20Sopenharmony_ci{
15418c2ecf20Sopenharmony_ci	struct perf_counts_values count;
15428c2ecf20Sopenharmony_ci	size_t nv = scale ? 3 : 1;
15438c2ecf20Sopenharmony_ci
15448c2ecf20Sopenharmony_ci	if (FD(evsel, cpu, thread) < 0)
15458c2ecf20Sopenharmony_ci		return -EINVAL;
15468c2ecf20Sopenharmony_ci
15478c2ecf20Sopenharmony_ci	if (evsel->counts == NULL && evsel__alloc_counts(evsel, cpu + 1, thread + 1) < 0)
15488c2ecf20Sopenharmony_ci		return -ENOMEM;
15498c2ecf20Sopenharmony_ci
15508c2ecf20Sopenharmony_ci	if (readn(FD(evsel, cpu, thread), &count, nv * sizeof(u64)) <= 0)
15518c2ecf20Sopenharmony_ci		return -errno;
15528c2ecf20Sopenharmony_ci
15538c2ecf20Sopenharmony_ci	evsel__compute_deltas(evsel, cpu, thread, &count);
15548c2ecf20Sopenharmony_ci	perf_counts_values__scale(&count, scale, NULL);
15558c2ecf20Sopenharmony_ci	*perf_counts(evsel->counts, cpu, thread) = count;
15568c2ecf20Sopenharmony_ci	return 0;
15578c2ecf20Sopenharmony_ci}
15588c2ecf20Sopenharmony_ci
15598c2ecf20Sopenharmony_cistatic int get_group_fd(struct evsel *evsel, int cpu, int thread)
15608c2ecf20Sopenharmony_ci{
15618c2ecf20Sopenharmony_ci	struct evsel *leader = evsel->leader;
15628c2ecf20Sopenharmony_ci	int fd;
15638c2ecf20Sopenharmony_ci
15648c2ecf20Sopenharmony_ci	if (evsel__is_group_leader(evsel))
15658c2ecf20Sopenharmony_ci		return -1;
15668c2ecf20Sopenharmony_ci
15678c2ecf20Sopenharmony_ci	/*
15688c2ecf20Sopenharmony_ci	 * Leader must be already processed/open,
15698c2ecf20Sopenharmony_ci	 * if not it's a bug.
15708c2ecf20Sopenharmony_ci	 */
15718c2ecf20Sopenharmony_ci	BUG_ON(!leader->core.fd);
15728c2ecf20Sopenharmony_ci
15738c2ecf20Sopenharmony_ci	fd = FD(leader, cpu, thread);
15748c2ecf20Sopenharmony_ci	BUG_ON(fd == -1);
15758c2ecf20Sopenharmony_ci
15768c2ecf20Sopenharmony_ci	return fd;
15778c2ecf20Sopenharmony_ci}
15788c2ecf20Sopenharmony_ci
15798c2ecf20Sopenharmony_cistatic void perf_evsel__remove_fd(struct evsel *pos,
15808c2ecf20Sopenharmony_ci				  int nr_cpus, int nr_threads,
15818c2ecf20Sopenharmony_ci				  int thread_idx)
15828c2ecf20Sopenharmony_ci{
15838c2ecf20Sopenharmony_ci	for (int cpu = 0; cpu < nr_cpus; cpu++)
15848c2ecf20Sopenharmony_ci		for (int thread = thread_idx; thread < nr_threads - 1; thread++)
15858c2ecf20Sopenharmony_ci			FD(pos, cpu, thread) = FD(pos, cpu, thread + 1);
15868c2ecf20Sopenharmony_ci}
15878c2ecf20Sopenharmony_ci
15888c2ecf20Sopenharmony_cistatic int update_fds(struct evsel *evsel,
15898c2ecf20Sopenharmony_ci		      int nr_cpus, int cpu_idx,
15908c2ecf20Sopenharmony_ci		      int nr_threads, int thread_idx)
15918c2ecf20Sopenharmony_ci{
15928c2ecf20Sopenharmony_ci	struct evsel *pos;
15938c2ecf20Sopenharmony_ci
15948c2ecf20Sopenharmony_ci	if (cpu_idx >= nr_cpus || thread_idx >= nr_threads)
15958c2ecf20Sopenharmony_ci		return -EINVAL;
15968c2ecf20Sopenharmony_ci
15978c2ecf20Sopenharmony_ci	evlist__for_each_entry(evsel->evlist, pos) {
15988c2ecf20Sopenharmony_ci		nr_cpus = pos != evsel ? nr_cpus : cpu_idx;
15998c2ecf20Sopenharmony_ci
16008c2ecf20Sopenharmony_ci		perf_evsel__remove_fd(pos, nr_cpus, nr_threads, thread_idx);
16018c2ecf20Sopenharmony_ci
16028c2ecf20Sopenharmony_ci		/*
16038c2ecf20Sopenharmony_ci		 * Since fds for next evsel has not been created,
16048c2ecf20Sopenharmony_ci		 * there is no need to iterate whole event list.
16058c2ecf20Sopenharmony_ci		 */
16068c2ecf20Sopenharmony_ci		if (pos == evsel)
16078c2ecf20Sopenharmony_ci			break;
16088c2ecf20Sopenharmony_ci	}
16098c2ecf20Sopenharmony_ci	return 0;
16108c2ecf20Sopenharmony_ci}
16118c2ecf20Sopenharmony_ci
16128c2ecf20Sopenharmony_cistatic bool ignore_missing_thread(struct evsel *evsel,
16138c2ecf20Sopenharmony_ci				  int nr_cpus, int cpu,
16148c2ecf20Sopenharmony_ci				  struct perf_thread_map *threads,
16158c2ecf20Sopenharmony_ci				  int thread, int err)
16168c2ecf20Sopenharmony_ci{
16178c2ecf20Sopenharmony_ci	pid_t ignore_pid = perf_thread_map__pid(threads, thread);
16188c2ecf20Sopenharmony_ci
16198c2ecf20Sopenharmony_ci	if (!evsel->ignore_missing_thread)
16208c2ecf20Sopenharmony_ci		return false;
16218c2ecf20Sopenharmony_ci
16228c2ecf20Sopenharmony_ci	/* The system wide setup does not work with threads. */
16238c2ecf20Sopenharmony_ci	if (evsel->core.system_wide)
16248c2ecf20Sopenharmony_ci		return false;
16258c2ecf20Sopenharmony_ci
16268c2ecf20Sopenharmony_ci	/* The -ESRCH is perf event syscall errno for pid's not found. */
16278c2ecf20Sopenharmony_ci	if (err != -ESRCH)
16288c2ecf20Sopenharmony_ci		return false;
16298c2ecf20Sopenharmony_ci
16308c2ecf20Sopenharmony_ci	/* If there's only one thread, let it fail. */
16318c2ecf20Sopenharmony_ci	if (threads->nr == 1)
16328c2ecf20Sopenharmony_ci		return false;
16338c2ecf20Sopenharmony_ci
16348c2ecf20Sopenharmony_ci	/*
16358c2ecf20Sopenharmony_ci	 * We should remove fd for missing_thread first
16368c2ecf20Sopenharmony_ci	 * because thread_map__remove() will decrease threads->nr.
16378c2ecf20Sopenharmony_ci	 */
16388c2ecf20Sopenharmony_ci	if (update_fds(evsel, nr_cpus, cpu, threads->nr, thread))
16398c2ecf20Sopenharmony_ci		return false;
16408c2ecf20Sopenharmony_ci
16418c2ecf20Sopenharmony_ci	if (thread_map__remove(threads, thread))
16428c2ecf20Sopenharmony_ci		return false;
16438c2ecf20Sopenharmony_ci
16448c2ecf20Sopenharmony_ci	pr_warning("WARNING: Ignored open failure for pid %d\n",
16458c2ecf20Sopenharmony_ci		   ignore_pid);
16468c2ecf20Sopenharmony_ci	return true;
16478c2ecf20Sopenharmony_ci}
16488c2ecf20Sopenharmony_ci
16498c2ecf20Sopenharmony_cistatic int __open_attr__fprintf(FILE *fp, const char *name, const char *val,
16508c2ecf20Sopenharmony_ci				void *priv __maybe_unused)
16518c2ecf20Sopenharmony_ci{
16528c2ecf20Sopenharmony_ci	return fprintf(fp, "  %-32s %s\n", name, val);
16538c2ecf20Sopenharmony_ci}
16548c2ecf20Sopenharmony_ci
16558c2ecf20Sopenharmony_cistatic void display_attr(struct perf_event_attr *attr)
16568c2ecf20Sopenharmony_ci{
16578c2ecf20Sopenharmony_ci	if (verbose >= 2 || debug_peo_args) {
16588c2ecf20Sopenharmony_ci		fprintf(stderr, "%.60s\n", graph_dotted_line);
16598c2ecf20Sopenharmony_ci		fprintf(stderr, "perf_event_attr:\n");
16608c2ecf20Sopenharmony_ci		perf_event_attr__fprintf(stderr, attr, __open_attr__fprintf, NULL);
16618c2ecf20Sopenharmony_ci		fprintf(stderr, "%.60s\n", graph_dotted_line);
16628c2ecf20Sopenharmony_ci	}
16638c2ecf20Sopenharmony_ci}
16648c2ecf20Sopenharmony_ci
16658c2ecf20Sopenharmony_cistatic int perf_event_open(struct evsel *evsel,
16668c2ecf20Sopenharmony_ci			   pid_t pid, int cpu, int group_fd,
16678c2ecf20Sopenharmony_ci			   unsigned long flags)
16688c2ecf20Sopenharmony_ci{
16698c2ecf20Sopenharmony_ci	int precise_ip = evsel->core.attr.precise_ip;
16708c2ecf20Sopenharmony_ci	int fd;
16718c2ecf20Sopenharmony_ci
16728c2ecf20Sopenharmony_ci	while (1) {
16738c2ecf20Sopenharmony_ci		pr_debug2_peo("sys_perf_event_open: pid %d  cpu %d  group_fd %d  flags %#lx",
16748c2ecf20Sopenharmony_ci			  pid, cpu, group_fd, flags);
16758c2ecf20Sopenharmony_ci
16768c2ecf20Sopenharmony_ci		fd = sys_perf_event_open(&evsel->core.attr, pid, cpu, group_fd, flags);
16778c2ecf20Sopenharmony_ci		if (fd >= 0)
16788c2ecf20Sopenharmony_ci			break;
16798c2ecf20Sopenharmony_ci
16808c2ecf20Sopenharmony_ci		/* Do not try less precise if not requested. */
16818c2ecf20Sopenharmony_ci		if (!evsel->precise_max)
16828c2ecf20Sopenharmony_ci			break;
16838c2ecf20Sopenharmony_ci
16848c2ecf20Sopenharmony_ci		/*
16858c2ecf20Sopenharmony_ci		 * We tried all the precise_ip values, and it's
16868c2ecf20Sopenharmony_ci		 * still failing, so leave it to standard fallback.
16878c2ecf20Sopenharmony_ci		 */
16888c2ecf20Sopenharmony_ci		if (!evsel->core.attr.precise_ip) {
16898c2ecf20Sopenharmony_ci			evsel->core.attr.precise_ip = precise_ip;
16908c2ecf20Sopenharmony_ci			break;
16918c2ecf20Sopenharmony_ci		}
16928c2ecf20Sopenharmony_ci
16938c2ecf20Sopenharmony_ci		pr_debug2_peo("\nsys_perf_event_open failed, error %d\n", -ENOTSUP);
16948c2ecf20Sopenharmony_ci		evsel->core.attr.precise_ip--;
16958c2ecf20Sopenharmony_ci		pr_debug2_peo("decreasing precise_ip by one (%d)\n", evsel->core.attr.precise_ip);
16968c2ecf20Sopenharmony_ci		display_attr(&evsel->core.attr);
16978c2ecf20Sopenharmony_ci	}
16988c2ecf20Sopenharmony_ci
16998c2ecf20Sopenharmony_ci	return fd;
17008c2ecf20Sopenharmony_ci}
17018c2ecf20Sopenharmony_ci
17028c2ecf20Sopenharmony_cistatic int evsel__open_cpu(struct evsel *evsel, struct perf_cpu_map *cpus,
17038c2ecf20Sopenharmony_ci		struct perf_thread_map *threads,
17048c2ecf20Sopenharmony_ci		int start_cpu, int end_cpu)
17058c2ecf20Sopenharmony_ci{
17068c2ecf20Sopenharmony_ci	int cpu, thread, nthreads;
17078c2ecf20Sopenharmony_ci	unsigned long flags = PERF_FLAG_FD_CLOEXEC;
17088c2ecf20Sopenharmony_ci	int pid = -1, err, old_errno;
17098c2ecf20Sopenharmony_ci	enum { NO_CHANGE, SET_TO_MAX, INCREASED_MAX } set_rlimit = NO_CHANGE;
17108c2ecf20Sopenharmony_ci
17118c2ecf20Sopenharmony_ci	if ((perf_missing_features.write_backward && evsel->core.attr.write_backward) ||
17128c2ecf20Sopenharmony_ci	    (perf_missing_features.aux_output     && evsel->core.attr.aux_output))
17138c2ecf20Sopenharmony_ci		return -EINVAL;
17148c2ecf20Sopenharmony_ci
17158c2ecf20Sopenharmony_ci	if (cpus == NULL) {
17168c2ecf20Sopenharmony_ci		static struct perf_cpu_map *empty_cpu_map;
17178c2ecf20Sopenharmony_ci
17188c2ecf20Sopenharmony_ci		if (empty_cpu_map == NULL) {
17198c2ecf20Sopenharmony_ci			empty_cpu_map = perf_cpu_map__dummy_new();
17208c2ecf20Sopenharmony_ci			if (empty_cpu_map == NULL)
17218c2ecf20Sopenharmony_ci				return -ENOMEM;
17228c2ecf20Sopenharmony_ci		}
17238c2ecf20Sopenharmony_ci
17248c2ecf20Sopenharmony_ci		cpus = empty_cpu_map;
17258c2ecf20Sopenharmony_ci	}
17268c2ecf20Sopenharmony_ci
17278c2ecf20Sopenharmony_ci	if (threads == NULL) {
17288c2ecf20Sopenharmony_ci		static struct perf_thread_map *empty_thread_map;
17298c2ecf20Sopenharmony_ci
17308c2ecf20Sopenharmony_ci		if (empty_thread_map == NULL) {
17318c2ecf20Sopenharmony_ci			empty_thread_map = thread_map__new_by_tid(-1);
17328c2ecf20Sopenharmony_ci			if (empty_thread_map == NULL)
17338c2ecf20Sopenharmony_ci				return -ENOMEM;
17348c2ecf20Sopenharmony_ci		}
17358c2ecf20Sopenharmony_ci
17368c2ecf20Sopenharmony_ci		threads = empty_thread_map;
17378c2ecf20Sopenharmony_ci	}
17388c2ecf20Sopenharmony_ci
17398c2ecf20Sopenharmony_ci	if (evsel->core.system_wide)
17408c2ecf20Sopenharmony_ci		nthreads = 1;
17418c2ecf20Sopenharmony_ci	else
17428c2ecf20Sopenharmony_ci		nthreads = threads->nr;
17438c2ecf20Sopenharmony_ci
17448c2ecf20Sopenharmony_ci	if (evsel->core.fd == NULL &&
17458c2ecf20Sopenharmony_ci	    perf_evsel__alloc_fd(&evsel->core, cpus->nr, nthreads) < 0)
17468c2ecf20Sopenharmony_ci		return -ENOMEM;
17478c2ecf20Sopenharmony_ci
17488c2ecf20Sopenharmony_ci	if (evsel->cgrp) {
17498c2ecf20Sopenharmony_ci		flags |= PERF_FLAG_PID_CGROUP;
17508c2ecf20Sopenharmony_ci		pid = evsel->cgrp->fd;
17518c2ecf20Sopenharmony_ci	}
17528c2ecf20Sopenharmony_ci
17538c2ecf20Sopenharmony_cifallback_missing_features:
17548c2ecf20Sopenharmony_ci	if (perf_missing_features.clockid_wrong)
17558c2ecf20Sopenharmony_ci		evsel->core.attr.clockid = CLOCK_MONOTONIC; /* should always work */
17568c2ecf20Sopenharmony_ci	if (perf_missing_features.clockid) {
17578c2ecf20Sopenharmony_ci		evsel->core.attr.use_clockid = 0;
17588c2ecf20Sopenharmony_ci		evsel->core.attr.clockid = 0;
17598c2ecf20Sopenharmony_ci	}
17608c2ecf20Sopenharmony_ci	if (perf_missing_features.cloexec)
17618c2ecf20Sopenharmony_ci		flags &= ~(unsigned long)PERF_FLAG_FD_CLOEXEC;
17628c2ecf20Sopenharmony_ci	if (perf_missing_features.mmap2)
17638c2ecf20Sopenharmony_ci		evsel->core.attr.mmap2 = 0;
17648c2ecf20Sopenharmony_ci	if (perf_missing_features.exclude_guest)
17658c2ecf20Sopenharmony_ci		evsel->core.attr.exclude_guest = evsel->core.attr.exclude_host = 0;
17668c2ecf20Sopenharmony_ci	if (perf_missing_features.lbr_flags)
17678c2ecf20Sopenharmony_ci		evsel->core.attr.branch_sample_type &= ~(PERF_SAMPLE_BRANCH_NO_FLAGS |
17688c2ecf20Sopenharmony_ci				     PERF_SAMPLE_BRANCH_NO_CYCLES);
17698c2ecf20Sopenharmony_ci	if (perf_missing_features.group_read && evsel->core.attr.inherit)
17708c2ecf20Sopenharmony_ci		evsel->core.attr.read_format &= ~(PERF_FORMAT_GROUP|PERF_FORMAT_ID);
17718c2ecf20Sopenharmony_ci	if (perf_missing_features.ksymbol)
17728c2ecf20Sopenharmony_ci		evsel->core.attr.ksymbol = 0;
17738c2ecf20Sopenharmony_ci	if (perf_missing_features.bpf)
17748c2ecf20Sopenharmony_ci		evsel->core.attr.bpf_event = 0;
17758c2ecf20Sopenharmony_ci	if (perf_missing_features.branch_hw_idx)
17768c2ecf20Sopenharmony_ci		evsel->core.attr.branch_sample_type &= ~PERF_SAMPLE_BRANCH_HW_INDEX;
17778c2ecf20Sopenharmony_ciretry_sample_id:
17788c2ecf20Sopenharmony_ci	if (perf_missing_features.sample_id_all)
17798c2ecf20Sopenharmony_ci		evsel->core.attr.sample_id_all = 0;
17808c2ecf20Sopenharmony_ci
17818c2ecf20Sopenharmony_ci	display_attr(&evsel->core.attr);
17828c2ecf20Sopenharmony_ci
17838c2ecf20Sopenharmony_ci	for (cpu = start_cpu; cpu < end_cpu; cpu++) {
17848c2ecf20Sopenharmony_ci
17858c2ecf20Sopenharmony_ci		for (thread = 0; thread < nthreads; thread++) {
17868c2ecf20Sopenharmony_ci			int fd, group_fd;
17878c2ecf20Sopenharmony_ci
17888c2ecf20Sopenharmony_ci			if (!evsel->cgrp && !evsel->core.system_wide)
17898c2ecf20Sopenharmony_ci				pid = perf_thread_map__pid(threads, thread);
17908c2ecf20Sopenharmony_ci
17918c2ecf20Sopenharmony_ci			group_fd = get_group_fd(evsel, cpu, thread);
17928c2ecf20Sopenharmony_ciretry_open:
17938c2ecf20Sopenharmony_ci			test_attr__ready();
17948c2ecf20Sopenharmony_ci
17958c2ecf20Sopenharmony_ci			fd = perf_event_open(evsel, pid, cpus->map[cpu],
17968c2ecf20Sopenharmony_ci					     group_fd, flags);
17978c2ecf20Sopenharmony_ci
17988c2ecf20Sopenharmony_ci			FD(evsel, cpu, thread) = fd;
17998c2ecf20Sopenharmony_ci
18008c2ecf20Sopenharmony_ci			if (unlikely(test_attr__enabled)) {
18018c2ecf20Sopenharmony_ci				test_attr__open(&evsel->core.attr, pid, cpus->map[cpu],
18028c2ecf20Sopenharmony_ci						fd, group_fd, flags);
18038c2ecf20Sopenharmony_ci			}
18048c2ecf20Sopenharmony_ci
18058c2ecf20Sopenharmony_ci			if (fd < 0) {
18068c2ecf20Sopenharmony_ci				err = -errno;
18078c2ecf20Sopenharmony_ci
18088c2ecf20Sopenharmony_ci				if (ignore_missing_thread(evsel, cpus->nr, cpu, threads, thread, err)) {
18098c2ecf20Sopenharmony_ci					/*
18108c2ecf20Sopenharmony_ci					 * We just removed 1 thread, so take a step
18118c2ecf20Sopenharmony_ci					 * back on thread index and lower the upper
18128c2ecf20Sopenharmony_ci					 * nthreads limit.
18138c2ecf20Sopenharmony_ci					 */
18148c2ecf20Sopenharmony_ci					nthreads--;
18158c2ecf20Sopenharmony_ci					thread--;
18168c2ecf20Sopenharmony_ci
18178c2ecf20Sopenharmony_ci					/* ... and pretend like nothing have happened. */
18188c2ecf20Sopenharmony_ci					err = 0;
18198c2ecf20Sopenharmony_ci					continue;
18208c2ecf20Sopenharmony_ci				}
18218c2ecf20Sopenharmony_ci
18228c2ecf20Sopenharmony_ci				pr_debug2_peo("\nsys_perf_event_open failed, error %d\n",
18238c2ecf20Sopenharmony_ci					  err);
18248c2ecf20Sopenharmony_ci				goto try_fallback;
18258c2ecf20Sopenharmony_ci			}
18268c2ecf20Sopenharmony_ci
18278c2ecf20Sopenharmony_ci			pr_debug2_peo(" = %d\n", fd);
18288c2ecf20Sopenharmony_ci
18298c2ecf20Sopenharmony_ci			if (evsel->bpf_fd >= 0) {
18308c2ecf20Sopenharmony_ci				int evt_fd = fd;
18318c2ecf20Sopenharmony_ci				int bpf_fd = evsel->bpf_fd;
18328c2ecf20Sopenharmony_ci
18338c2ecf20Sopenharmony_ci				err = ioctl(evt_fd,
18348c2ecf20Sopenharmony_ci					    PERF_EVENT_IOC_SET_BPF,
18358c2ecf20Sopenharmony_ci					    bpf_fd);
18368c2ecf20Sopenharmony_ci				if (err && errno != EEXIST) {
18378c2ecf20Sopenharmony_ci					pr_err("failed to attach bpf fd %d: %s\n",
18388c2ecf20Sopenharmony_ci					       bpf_fd, strerror(errno));
18398c2ecf20Sopenharmony_ci					err = -EINVAL;
18408c2ecf20Sopenharmony_ci					goto out_close;
18418c2ecf20Sopenharmony_ci				}
18428c2ecf20Sopenharmony_ci			}
18438c2ecf20Sopenharmony_ci
18448c2ecf20Sopenharmony_ci			set_rlimit = NO_CHANGE;
18458c2ecf20Sopenharmony_ci
18468c2ecf20Sopenharmony_ci			/*
18478c2ecf20Sopenharmony_ci			 * If we succeeded but had to kill clockid, fail and
18488c2ecf20Sopenharmony_ci			 * have evsel__open_strerror() print us a nice error.
18498c2ecf20Sopenharmony_ci			 */
18508c2ecf20Sopenharmony_ci			if (perf_missing_features.clockid ||
18518c2ecf20Sopenharmony_ci			    perf_missing_features.clockid_wrong) {
18528c2ecf20Sopenharmony_ci				err = -EINVAL;
18538c2ecf20Sopenharmony_ci				goto out_close;
18548c2ecf20Sopenharmony_ci			}
18558c2ecf20Sopenharmony_ci		}
18568c2ecf20Sopenharmony_ci	}
18578c2ecf20Sopenharmony_ci
18588c2ecf20Sopenharmony_ci	return 0;
18598c2ecf20Sopenharmony_ci
18608c2ecf20Sopenharmony_citry_fallback:
18618c2ecf20Sopenharmony_ci	/*
18628c2ecf20Sopenharmony_ci	 * perf stat needs between 5 and 22 fds per CPU. When we run out
18638c2ecf20Sopenharmony_ci	 * of them try to increase the limits.
18648c2ecf20Sopenharmony_ci	 */
18658c2ecf20Sopenharmony_ci	if (err == -EMFILE && set_rlimit < INCREASED_MAX) {
18668c2ecf20Sopenharmony_ci		struct rlimit l;
18678c2ecf20Sopenharmony_ci
18688c2ecf20Sopenharmony_ci		old_errno = errno;
18698c2ecf20Sopenharmony_ci		if (getrlimit(RLIMIT_NOFILE, &l) == 0) {
18708c2ecf20Sopenharmony_ci			if (set_rlimit == NO_CHANGE)
18718c2ecf20Sopenharmony_ci				l.rlim_cur = l.rlim_max;
18728c2ecf20Sopenharmony_ci			else {
18738c2ecf20Sopenharmony_ci				l.rlim_cur = l.rlim_max + 1000;
18748c2ecf20Sopenharmony_ci				l.rlim_max = l.rlim_cur;
18758c2ecf20Sopenharmony_ci			}
18768c2ecf20Sopenharmony_ci			if (setrlimit(RLIMIT_NOFILE, &l) == 0) {
18778c2ecf20Sopenharmony_ci				set_rlimit++;
18788c2ecf20Sopenharmony_ci				errno = old_errno;
18798c2ecf20Sopenharmony_ci				goto retry_open;
18808c2ecf20Sopenharmony_ci			}
18818c2ecf20Sopenharmony_ci		}
18828c2ecf20Sopenharmony_ci		errno = old_errno;
18838c2ecf20Sopenharmony_ci	}
18848c2ecf20Sopenharmony_ci
18858c2ecf20Sopenharmony_ci	if (err != -EINVAL || cpu > 0 || thread > 0)
18868c2ecf20Sopenharmony_ci		goto out_close;
18878c2ecf20Sopenharmony_ci
18888c2ecf20Sopenharmony_ci	/*
18898c2ecf20Sopenharmony_ci	 * Must probe features in the order they were added to the
18908c2ecf20Sopenharmony_ci	 * perf_event_attr interface.
18918c2ecf20Sopenharmony_ci	 */
18928c2ecf20Sopenharmony_ci        if (!perf_missing_features.cgroup && evsel->core.attr.cgroup) {
18938c2ecf20Sopenharmony_ci		perf_missing_features.cgroup = true;
18948c2ecf20Sopenharmony_ci		pr_debug2_peo("Kernel has no cgroup sampling support, bailing out\n");
18958c2ecf20Sopenharmony_ci		goto out_close;
18968c2ecf20Sopenharmony_ci        } else if (!perf_missing_features.branch_hw_idx &&
18978c2ecf20Sopenharmony_ci	    (evsel->core.attr.branch_sample_type & PERF_SAMPLE_BRANCH_HW_INDEX)) {
18988c2ecf20Sopenharmony_ci		perf_missing_features.branch_hw_idx = true;
18998c2ecf20Sopenharmony_ci		pr_debug2("switching off branch HW index support\n");
19008c2ecf20Sopenharmony_ci		goto fallback_missing_features;
19018c2ecf20Sopenharmony_ci	} else if (!perf_missing_features.aux_output && evsel->core.attr.aux_output) {
19028c2ecf20Sopenharmony_ci		perf_missing_features.aux_output = true;
19038c2ecf20Sopenharmony_ci		pr_debug2_peo("Kernel has no attr.aux_output support, bailing out\n");
19048c2ecf20Sopenharmony_ci		goto out_close;
19058c2ecf20Sopenharmony_ci	} else if (!perf_missing_features.bpf && evsel->core.attr.bpf_event) {
19068c2ecf20Sopenharmony_ci		perf_missing_features.bpf = true;
19078c2ecf20Sopenharmony_ci		pr_debug2_peo("switching off bpf_event\n");
19088c2ecf20Sopenharmony_ci		goto fallback_missing_features;
19098c2ecf20Sopenharmony_ci	} else if (!perf_missing_features.ksymbol && evsel->core.attr.ksymbol) {
19108c2ecf20Sopenharmony_ci		perf_missing_features.ksymbol = true;
19118c2ecf20Sopenharmony_ci		pr_debug2_peo("switching off ksymbol\n");
19128c2ecf20Sopenharmony_ci		goto fallback_missing_features;
19138c2ecf20Sopenharmony_ci	} else if (!perf_missing_features.write_backward && evsel->core.attr.write_backward) {
19148c2ecf20Sopenharmony_ci		perf_missing_features.write_backward = true;
19158c2ecf20Sopenharmony_ci		pr_debug2_peo("switching off write_backward\n");
19168c2ecf20Sopenharmony_ci		goto out_close;
19178c2ecf20Sopenharmony_ci	} else if (!perf_missing_features.clockid_wrong && evsel->core.attr.use_clockid) {
19188c2ecf20Sopenharmony_ci		perf_missing_features.clockid_wrong = true;
19198c2ecf20Sopenharmony_ci		pr_debug2_peo("switching off clockid\n");
19208c2ecf20Sopenharmony_ci		goto fallback_missing_features;
19218c2ecf20Sopenharmony_ci	} else if (!perf_missing_features.clockid && evsel->core.attr.use_clockid) {
19228c2ecf20Sopenharmony_ci		perf_missing_features.clockid = true;
19238c2ecf20Sopenharmony_ci		pr_debug2_peo("switching off use_clockid\n");
19248c2ecf20Sopenharmony_ci		goto fallback_missing_features;
19258c2ecf20Sopenharmony_ci	} else if (!perf_missing_features.cloexec && (flags & PERF_FLAG_FD_CLOEXEC)) {
19268c2ecf20Sopenharmony_ci		perf_missing_features.cloexec = true;
19278c2ecf20Sopenharmony_ci		pr_debug2_peo("switching off cloexec flag\n");
19288c2ecf20Sopenharmony_ci		goto fallback_missing_features;
19298c2ecf20Sopenharmony_ci	} else if (!perf_missing_features.mmap2 && evsel->core.attr.mmap2) {
19308c2ecf20Sopenharmony_ci		perf_missing_features.mmap2 = true;
19318c2ecf20Sopenharmony_ci		pr_debug2_peo("switching off mmap2\n");
19328c2ecf20Sopenharmony_ci		goto fallback_missing_features;
19338c2ecf20Sopenharmony_ci	} else if (!perf_missing_features.exclude_guest &&
19348c2ecf20Sopenharmony_ci		   (evsel->core.attr.exclude_guest || evsel->core.attr.exclude_host)) {
19358c2ecf20Sopenharmony_ci		perf_missing_features.exclude_guest = true;
19368c2ecf20Sopenharmony_ci		pr_debug2_peo("switching off exclude_guest, exclude_host\n");
19378c2ecf20Sopenharmony_ci		goto fallback_missing_features;
19388c2ecf20Sopenharmony_ci	} else if (!perf_missing_features.sample_id_all) {
19398c2ecf20Sopenharmony_ci		perf_missing_features.sample_id_all = true;
19408c2ecf20Sopenharmony_ci		pr_debug2_peo("switching off sample_id_all\n");
19418c2ecf20Sopenharmony_ci		goto retry_sample_id;
19428c2ecf20Sopenharmony_ci	} else if (!perf_missing_features.lbr_flags &&
19438c2ecf20Sopenharmony_ci			(evsel->core.attr.branch_sample_type &
19448c2ecf20Sopenharmony_ci			 (PERF_SAMPLE_BRANCH_NO_CYCLES |
19458c2ecf20Sopenharmony_ci			  PERF_SAMPLE_BRANCH_NO_FLAGS))) {
19468c2ecf20Sopenharmony_ci		perf_missing_features.lbr_flags = true;
19478c2ecf20Sopenharmony_ci		pr_debug2_peo("switching off branch sample type no (cycles/flags)\n");
19488c2ecf20Sopenharmony_ci		goto fallback_missing_features;
19498c2ecf20Sopenharmony_ci	} else if (!perf_missing_features.group_read &&
19508c2ecf20Sopenharmony_ci		    evsel->core.attr.inherit &&
19518c2ecf20Sopenharmony_ci		   (evsel->core.attr.read_format & PERF_FORMAT_GROUP) &&
19528c2ecf20Sopenharmony_ci		   evsel__is_group_leader(evsel)) {
19538c2ecf20Sopenharmony_ci		perf_missing_features.group_read = true;
19548c2ecf20Sopenharmony_ci		pr_debug2_peo("switching off group read\n");
19558c2ecf20Sopenharmony_ci		goto fallback_missing_features;
19568c2ecf20Sopenharmony_ci	}
19578c2ecf20Sopenharmony_ciout_close:
19588c2ecf20Sopenharmony_ci	if (err)
19598c2ecf20Sopenharmony_ci		threads->err_thread = thread;
19608c2ecf20Sopenharmony_ci
19618c2ecf20Sopenharmony_ci	old_errno = errno;
19628c2ecf20Sopenharmony_ci	do {
19638c2ecf20Sopenharmony_ci		while (--thread >= 0) {
19648c2ecf20Sopenharmony_ci			if (FD(evsel, cpu, thread) >= 0)
19658c2ecf20Sopenharmony_ci				close(FD(evsel, cpu, thread));
19668c2ecf20Sopenharmony_ci			FD(evsel, cpu, thread) = -1;
19678c2ecf20Sopenharmony_ci		}
19688c2ecf20Sopenharmony_ci		thread = nthreads;
19698c2ecf20Sopenharmony_ci	} while (--cpu >= 0);
19708c2ecf20Sopenharmony_ci	errno = old_errno;
19718c2ecf20Sopenharmony_ci	return err;
19728c2ecf20Sopenharmony_ci}
19738c2ecf20Sopenharmony_ci
19748c2ecf20Sopenharmony_ciint evsel__open(struct evsel *evsel, struct perf_cpu_map *cpus,
19758c2ecf20Sopenharmony_ci		struct perf_thread_map *threads)
19768c2ecf20Sopenharmony_ci{
19778c2ecf20Sopenharmony_ci	return evsel__open_cpu(evsel, cpus, threads, 0, cpus ? cpus->nr : 1);
19788c2ecf20Sopenharmony_ci}
19798c2ecf20Sopenharmony_ci
19808c2ecf20Sopenharmony_civoid evsel__close(struct evsel *evsel)
19818c2ecf20Sopenharmony_ci{
19828c2ecf20Sopenharmony_ci	perf_evsel__close(&evsel->core);
19838c2ecf20Sopenharmony_ci	perf_evsel__free_id(&evsel->core);
19848c2ecf20Sopenharmony_ci}
19858c2ecf20Sopenharmony_ci
19868c2ecf20Sopenharmony_ciint evsel__open_per_cpu(struct evsel *evsel, struct perf_cpu_map *cpus, int cpu)
19878c2ecf20Sopenharmony_ci{
19888c2ecf20Sopenharmony_ci	if (cpu == -1)
19898c2ecf20Sopenharmony_ci		return evsel__open_cpu(evsel, cpus, NULL, 0,
19908c2ecf20Sopenharmony_ci					cpus ? cpus->nr : 1);
19918c2ecf20Sopenharmony_ci
19928c2ecf20Sopenharmony_ci	return evsel__open_cpu(evsel, cpus, NULL, cpu, cpu + 1);
19938c2ecf20Sopenharmony_ci}
19948c2ecf20Sopenharmony_ci
19958c2ecf20Sopenharmony_ciint evsel__open_per_thread(struct evsel *evsel, struct perf_thread_map *threads)
19968c2ecf20Sopenharmony_ci{
19978c2ecf20Sopenharmony_ci	return evsel__open(evsel, NULL, threads);
19988c2ecf20Sopenharmony_ci}
19998c2ecf20Sopenharmony_ci
20008c2ecf20Sopenharmony_cistatic int perf_evsel__parse_id_sample(const struct evsel *evsel,
20018c2ecf20Sopenharmony_ci				       const union perf_event *event,
20028c2ecf20Sopenharmony_ci				       struct perf_sample *sample)
20038c2ecf20Sopenharmony_ci{
20048c2ecf20Sopenharmony_ci	u64 type = evsel->core.attr.sample_type;
20058c2ecf20Sopenharmony_ci	const __u64 *array = event->sample.array;
20068c2ecf20Sopenharmony_ci	bool swapped = evsel->needs_swap;
20078c2ecf20Sopenharmony_ci	union u64_swap u;
20088c2ecf20Sopenharmony_ci
20098c2ecf20Sopenharmony_ci	array += ((event->header.size -
20108c2ecf20Sopenharmony_ci		   sizeof(event->header)) / sizeof(u64)) - 1;
20118c2ecf20Sopenharmony_ci
20128c2ecf20Sopenharmony_ci	if (type & PERF_SAMPLE_IDENTIFIER) {
20138c2ecf20Sopenharmony_ci		sample->id = *array;
20148c2ecf20Sopenharmony_ci		array--;
20158c2ecf20Sopenharmony_ci	}
20168c2ecf20Sopenharmony_ci
20178c2ecf20Sopenharmony_ci	if (type & PERF_SAMPLE_CPU) {
20188c2ecf20Sopenharmony_ci		u.val64 = *array;
20198c2ecf20Sopenharmony_ci		if (swapped) {
20208c2ecf20Sopenharmony_ci			/* undo swap of u64, then swap on individual u32s */
20218c2ecf20Sopenharmony_ci			u.val64 = bswap_64(u.val64);
20228c2ecf20Sopenharmony_ci			u.val32[0] = bswap_32(u.val32[0]);
20238c2ecf20Sopenharmony_ci		}
20248c2ecf20Sopenharmony_ci
20258c2ecf20Sopenharmony_ci		sample->cpu = u.val32[0];
20268c2ecf20Sopenharmony_ci		array--;
20278c2ecf20Sopenharmony_ci	}
20288c2ecf20Sopenharmony_ci
20298c2ecf20Sopenharmony_ci	if (type & PERF_SAMPLE_STREAM_ID) {
20308c2ecf20Sopenharmony_ci		sample->stream_id = *array;
20318c2ecf20Sopenharmony_ci		array--;
20328c2ecf20Sopenharmony_ci	}
20338c2ecf20Sopenharmony_ci
20348c2ecf20Sopenharmony_ci	if (type & PERF_SAMPLE_ID) {
20358c2ecf20Sopenharmony_ci		sample->id = *array;
20368c2ecf20Sopenharmony_ci		array--;
20378c2ecf20Sopenharmony_ci	}
20388c2ecf20Sopenharmony_ci
20398c2ecf20Sopenharmony_ci	if (type & PERF_SAMPLE_TIME) {
20408c2ecf20Sopenharmony_ci		sample->time = *array;
20418c2ecf20Sopenharmony_ci		array--;
20428c2ecf20Sopenharmony_ci	}
20438c2ecf20Sopenharmony_ci
20448c2ecf20Sopenharmony_ci	if (type & PERF_SAMPLE_TID) {
20458c2ecf20Sopenharmony_ci		u.val64 = *array;
20468c2ecf20Sopenharmony_ci		if (swapped) {
20478c2ecf20Sopenharmony_ci			/* undo swap of u64, then swap on individual u32s */
20488c2ecf20Sopenharmony_ci			u.val64 = bswap_64(u.val64);
20498c2ecf20Sopenharmony_ci			u.val32[0] = bswap_32(u.val32[0]);
20508c2ecf20Sopenharmony_ci			u.val32[1] = bswap_32(u.val32[1]);
20518c2ecf20Sopenharmony_ci		}
20528c2ecf20Sopenharmony_ci
20538c2ecf20Sopenharmony_ci		sample->pid = u.val32[0];
20548c2ecf20Sopenharmony_ci		sample->tid = u.val32[1];
20558c2ecf20Sopenharmony_ci		array--;
20568c2ecf20Sopenharmony_ci	}
20578c2ecf20Sopenharmony_ci
20588c2ecf20Sopenharmony_ci	return 0;
20598c2ecf20Sopenharmony_ci}
20608c2ecf20Sopenharmony_ci
20618c2ecf20Sopenharmony_cistatic inline bool overflow(const void *endp, u16 max_size, const void *offset,
20628c2ecf20Sopenharmony_ci			    u64 size)
20638c2ecf20Sopenharmony_ci{
20648c2ecf20Sopenharmony_ci	return size > max_size || offset + size > endp;
20658c2ecf20Sopenharmony_ci}
20668c2ecf20Sopenharmony_ci
20678c2ecf20Sopenharmony_ci#define OVERFLOW_CHECK(offset, size, max_size)				\
20688c2ecf20Sopenharmony_ci	do {								\
20698c2ecf20Sopenharmony_ci		if (overflow(endp, (max_size), (offset), (size)))	\
20708c2ecf20Sopenharmony_ci			return -EFAULT;					\
20718c2ecf20Sopenharmony_ci	} while (0)
20728c2ecf20Sopenharmony_ci
20738c2ecf20Sopenharmony_ci#define OVERFLOW_CHECK_u64(offset) \
20748c2ecf20Sopenharmony_ci	OVERFLOW_CHECK(offset, sizeof(u64), sizeof(u64))
20758c2ecf20Sopenharmony_ci
20768c2ecf20Sopenharmony_cistatic int
20778c2ecf20Sopenharmony_ciperf_event__check_size(union perf_event *event, unsigned int sample_size)
20788c2ecf20Sopenharmony_ci{
20798c2ecf20Sopenharmony_ci	/*
20808c2ecf20Sopenharmony_ci	 * The evsel's sample_size is based on PERF_SAMPLE_MASK which includes
20818c2ecf20Sopenharmony_ci	 * up to PERF_SAMPLE_PERIOD.  After that overflow() must be used to
20828c2ecf20Sopenharmony_ci	 * check the format does not go past the end of the event.
20838c2ecf20Sopenharmony_ci	 */
20848c2ecf20Sopenharmony_ci	if (sample_size + sizeof(event->header) > event->header.size)
20858c2ecf20Sopenharmony_ci		return -EFAULT;
20868c2ecf20Sopenharmony_ci
20878c2ecf20Sopenharmony_ci	return 0;
20888c2ecf20Sopenharmony_ci}
20898c2ecf20Sopenharmony_ci
20908c2ecf20Sopenharmony_ciint evsel__parse_sample(struct evsel *evsel, union perf_event *event,
20918c2ecf20Sopenharmony_ci			struct perf_sample *data)
20928c2ecf20Sopenharmony_ci{
20938c2ecf20Sopenharmony_ci	u64 type = evsel->core.attr.sample_type;
20948c2ecf20Sopenharmony_ci	bool swapped = evsel->needs_swap;
20958c2ecf20Sopenharmony_ci	const __u64 *array;
20968c2ecf20Sopenharmony_ci	u16 max_size = event->header.size;
20978c2ecf20Sopenharmony_ci	const void *endp = (void *)event + max_size;
20988c2ecf20Sopenharmony_ci	u64 sz;
20998c2ecf20Sopenharmony_ci
21008c2ecf20Sopenharmony_ci	/*
21018c2ecf20Sopenharmony_ci	 * used for cross-endian analysis. See git commit 65014ab3
21028c2ecf20Sopenharmony_ci	 * for why this goofiness is needed.
21038c2ecf20Sopenharmony_ci	 */
21048c2ecf20Sopenharmony_ci	union u64_swap u;
21058c2ecf20Sopenharmony_ci
21068c2ecf20Sopenharmony_ci	memset(data, 0, sizeof(*data));
21078c2ecf20Sopenharmony_ci	data->cpu = data->pid = data->tid = -1;
21088c2ecf20Sopenharmony_ci	data->stream_id = data->id = data->time = -1ULL;
21098c2ecf20Sopenharmony_ci	data->period = evsel->core.attr.sample_period;
21108c2ecf20Sopenharmony_ci	data->cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
21118c2ecf20Sopenharmony_ci	data->misc    = event->header.misc;
21128c2ecf20Sopenharmony_ci	data->id = -1ULL;
21138c2ecf20Sopenharmony_ci	data->data_src = PERF_MEM_DATA_SRC_NONE;
21148c2ecf20Sopenharmony_ci
21158c2ecf20Sopenharmony_ci	if (event->header.type != PERF_RECORD_SAMPLE) {
21168c2ecf20Sopenharmony_ci		if (!evsel->core.attr.sample_id_all)
21178c2ecf20Sopenharmony_ci			return 0;
21188c2ecf20Sopenharmony_ci		return perf_evsel__parse_id_sample(evsel, event, data);
21198c2ecf20Sopenharmony_ci	}
21208c2ecf20Sopenharmony_ci
21218c2ecf20Sopenharmony_ci	array = event->sample.array;
21228c2ecf20Sopenharmony_ci
21238c2ecf20Sopenharmony_ci	if (perf_event__check_size(event, evsel->sample_size))
21248c2ecf20Sopenharmony_ci		return -EFAULT;
21258c2ecf20Sopenharmony_ci
21268c2ecf20Sopenharmony_ci	if (type & PERF_SAMPLE_IDENTIFIER) {
21278c2ecf20Sopenharmony_ci		data->id = *array;
21288c2ecf20Sopenharmony_ci		array++;
21298c2ecf20Sopenharmony_ci	}
21308c2ecf20Sopenharmony_ci
21318c2ecf20Sopenharmony_ci	if (type & PERF_SAMPLE_IP) {
21328c2ecf20Sopenharmony_ci		data->ip = *array;
21338c2ecf20Sopenharmony_ci		array++;
21348c2ecf20Sopenharmony_ci	}
21358c2ecf20Sopenharmony_ci
21368c2ecf20Sopenharmony_ci	if (type & PERF_SAMPLE_TID) {
21378c2ecf20Sopenharmony_ci		u.val64 = *array;
21388c2ecf20Sopenharmony_ci		if (swapped) {
21398c2ecf20Sopenharmony_ci			/* undo swap of u64, then swap on individual u32s */
21408c2ecf20Sopenharmony_ci			u.val64 = bswap_64(u.val64);
21418c2ecf20Sopenharmony_ci			u.val32[0] = bswap_32(u.val32[0]);
21428c2ecf20Sopenharmony_ci			u.val32[1] = bswap_32(u.val32[1]);
21438c2ecf20Sopenharmony_ci		}
21448c2ecf20Sopenharmony_ci
21458c2ecf20Sopenharmony_ci		data->pid = u.val32[0];
21468c2ecf20Sopenharmony_ci		data->tid = u.val32[1];
21478c2ecf20Sopenharmony_ci		array++;
21488c2ecf20Sopenharmony_ci	}
21498c2ecf20Sopenharmony_ci
21508c2ecf20Sopenharmony_ci	if (type & PERF_SAMPLE_TIME) {
21518c2ecf20Sopenharmony_ci		data->time = *array;
21528c2ecf20Sopenharmony_ci		array++;
21538c2ecf20Sopenharmony_ci	}
21548c2ecf20Sopenharmony_ci
21558c2ecf20Sopenharmony_ci	if (type & PERF_SAMPLE_ADDR) {
21568c2ecf20Sopenharmony_ci		data->addr = *array;
21578c2ecf20Sopenharmony_ci		array++;
21588c2ecf20Sopenharmony_ci	}
21598c2ecf20Sopenharmony_ci
21608c2ecf20Sopenharmony_ci	if (type & PERF_SAMPLE_ID) {
21618c2ecf20Sopenharmony_ci		data->id = *array;
21628c2ecf20Sopenharmony_ci		array++;
21638c2ecf20Sopenharmony_ci	}
21648c2ecf20Sopenharmony_ci
21658c2ecf20Sopenharmony_ci	if (type & PERF_SAMPLE_STREAM_ID) {
21668c2ecf20Sopenharmony_ci		data->stream_id = *array;
21678c2ecf20Sopenharmony_ci		array++;
21688c2ecf20Sopenharmony_ci	}
21698c2ecf20Sopenharmony_ci
21708c2ecf20Sopenharmony_ci	if (type & PERF_SAMPLE_CPU) {
21718c2ecf20Sopenharmony_ci
21728c2ecf20Sopenharmony_ci		u.val64 = *array;
21738c2ecf20Sopenharmony_ci		if (swapped) {
21748c2ecf20Sopenharmony_ci			/* undo swap of u64, then swap on individual u32s */
21758c2ecf20Sopenharmony_ci			u.val64 = bswap_64(u.val64);
21768c2ecf20Sopenharmony_ci			u.val32[0] = bswap_32(u.val32[0]);
21778c2ecf20Sopenharmony_ci		}
21788c2ecf20Sopenharmony_ci
21798c2ecf20Sopenharmony_ci		data->cpu = u.val32[0];
21808c2ecf20Sopenharmony_ci		array++;
21818c2ecf20Sopenharmony_ci	}
21828c2ecf20Sopenharmony_ci
21838c2ecf20Sopenharmony_ci	if (type & PERF_SAMPLE_PERIOD) {
21848c2ecf20Sopenharmony_ci		data->period = *array;
21858c2ecf20Sopenharmony_ci		array++;
21868c2ecf20Sopenharmony_ci	}
21878c2ecf20Sopenharmony_ci
21888c2ecf20Sopenharmony_ci	if (type & PERF_SAMPLE_READ) {
21898c2ecf20Sopenharmony_ci		u64 read_format = evsel->core.attr.read_format;
21908c2ecf20Sopenharmony_ci
21918c2ecf20Sopenharmony_ci		OVERFLOW_CHECK_u64(array);
21928c2ecf20Sopenharmony_ci		if (read_format & PERF_FORMAT_GROUP)
21938c2ecf20Sopenharmony_ci			data->read.group.nr = *array;
21948c2ecf20Sopenharmony_ci		else
21958c2ecf20Sopenharmony_ci			data->read.one.value = *array;
21968c2ecf20Sopenharmony_ci
21978c2ecf20Sopenharmony_ci		array++;
21988c2ecf20Sopenharmony_ci
21998c2ecf20Sopenharmony_ci		if (read_format & PERF_FORMAT_TOTAL_TIME_ENABLED) {
22008c2ecf20Sopenharmony_ci			OVERFLOW_CHECK_u64(array);
22018c2ecf20Sopenharmony_ci			data->read.time_enabled = *array;
22028c2ecf20Sopenharmony_ci			array++;
22038c2ecf20Sopenharmony_ci		}
22048c2ecf20Sopenharmony_ci
22058c2ecf20Sopenharmony_ci		if (read_format & PERF_FORMAT_TOTAL_TIME_RUNNING) {
22068c2ecf20Sopenharmony_ci			OVERFLOW_CHECK_u64(array);
22078c2ecf20Sopenharmony_ci			data->read.time_running = *array;
22088c2ecf20Sopenharmony_ci			array++;
22098c2ecf20Sopenharmony_ci		}
22108c2ecf20Sopenharmony_ci
22118c2ecf20Sopenharmony_ci		/* PERF_FORMAT_ID is forced for PERF_SAMPLE_READ */
22128c2ecf20Sopenharmony_ci		if (read_format & PERF_FORMAT_GROUP) {
22138c2ecf20Sopenharmony_ci			const u64 max_group_nr = UINT64_MAX /
22148c2ecf20Sopenharmony_ci					sizeof(struct sample_read_value);
22158c2ecf20Sopenharmony_ci
22168c2ecf20Sopenharmony_ci			if (data->read.group.nr > max_group_nr)
22178c2ecf20Sopenharmony_ci				return -EFAULT;
22188c2ecf20Sopenharmony_ci			sz = data->read.group.nr *
22198c2ecf20Sopenharmony_ci			     sizeof(struct sample_read_value);
22208c2ecf20Sopenharmony_ci			OVERFLOW_CHECK(array, sz, max_size);
22218c2ecf20Sopenharmony_ci			data->read.group.values =
22228c2ecf20Sopenharmony_ci					(struct sample_read_value *)array;
22238c2ecf20Sopenharmony_ci			array = (void *)array + sz;
22248c2ecf20Sopenharmony_ci		} else {
22258c2ecf20Sopenharmony_ci			OVERFLOW_CHECK_u64(array);
22268c2ecf20Sopenharmony_ci			data->read.one.id = *array;
22278c2ecf20Sopenharmony_ci			array++;
22288c2ecf20Sopenharmony_ci		}
22298c2ecf20Sopenharmony_ci	}
22308c2ecf20Sopenharmony_ci
22318c2ecf20Sopenharmony_ci	if (type & PERF_SAMPLE_CALLCHAIN) {
22328c2ecf20Sopenharmony_ci		const u64 max_callchain_nr = UINT64_MAX / sizeof(u64);
22338c2ecf20Sopenharmony_ci
22348c2ecf20Sopenharmony_ci		OVERFLOW_CHECK_u64(array);
22358c2ecf20Sopenharmony_ci		data->callchain = (struct ip_callchain *)array++;
22368c2ecf20Sopenharmony_ci		if (data->callchain->nr > max_callchain_nr)
22378c2ecf20Sopenharmony_ci			return -EFAULT;
22388c2ecf20Sopenharmony_ci		sz = data->callchain->nr * sizeof(u64);
22398c2ecf20Sopenharmony_ci		OVERFLOW_CHECK(array, sz, max_size);
22408c2ecf20Sopenharmony_ci		array = (void *)array + sz;
22418c2ecf20Sopenharmony_ci	}
22428c2ecf20Sopenharmony_ci
22438c2ecf20Sopenharmony_ci	if (type & PERF_SAMPLE_RAW) {
22448c2ecf20Sopenharmony_ci		OVERFLOW_CHECK_u64(array);
22458c2ecf20Sopenharmony_ci		u.val64 = *array;
22468c2ecf20Sopenharmony_ci
22478c2ecf20Sopenharmony_ci		/*
22488c2ecf20Sopenharmony_ci		 * Undo swap of u64, then swap on individual u32s,
22498c2ecf20Sopenharmony_ci		 * get the size of the raw area and undo all of the
22508c2ecf20Sopenharmony_ci		 * swap. The pevent interface handles endianity by
22518c2ecf20Sopenharmony_ci		 * itself.
22528c2ecf20Sopenharmony_ci		 */
22538c2ecf20Sopenharmony_ci		if (swapped) {
22548c2ecf20Sopenharmony_ci			u.val64 = bswap_64(u.val64);
22558c2ecf20Sopenharmony_ci			u.val32[0] = bswap_32(u.val32[0]);
22568c2ecf20Sopenharmony_ci			u.val32[1] = bswap_32(u.val32[1]);
22578c2ecf20Sopenharmony_ci		}
22588c2ecf20Sopenharmony_ci		data->raw_size = u.val32[0];
22598c2ecf20Sopenharmony_ci
22608c2ecf20Sopenharmony_ci		/*
22618c2ecf20Sopenharmony_ci		 * The raw data is aligned on 64bits including the
22628c2ecf20Sopenharmony_ci		 * u32 size, so it's safe to use mem_bswap_64.
22638c2ecf20Sopenharmony_ci		 */
22648c2ecf20Sopenharmony_ci		if (swapped)
22658c2ecf20Sopenharmony_ci			mem_bswap_64((void *) array, data->raw_size);
22668c2ecf20Sopenharmony_ci
22678c2ecf20Sopenharmony_ci		array = (void *)array + sizeof(u32);
22688c2ecf20Sopenharmony_ci
22698c2ecf20Sopenharmony_ci		OVERFLOW_CHECK(array, data->raw_size, max_size);
22708c2ecf20Sopenharmony_ci		data->raw_data = (void *)array;
22718c2ecf20Sopenharmony_ci		array = (void *)array + data->raw_size;
22728c2ecf20Sopenharmony_ci	}
22738c2ecf20Sopenharmony_ci
22748c2ecf20Sopenharmony_ci	if (type & PERF_SAMPLE_BRANCH_STACK) {
22758c2ecf20Sopenharmony_ci		const u64 max_branch_nr = UINT64_MAX /
22768c2ecf20Sopenharmony_ci					  sizeof(struct branch_entry);
22778c2ecf20Sopenharmony_ci
22788c2ecf20Sopenharmony_ci		OVERFLOW_CHECK_u64(array);
22798c2ecf20Sopenharmony_ci		data->branch_stack = (struct branch_stack *)array++;
22808c2ecf20Sopenharmony_ci
22818c2ecf20Sopenharmony_ci		if (data->branch_stack->nr > max_branch_nr)
22828c2ecf20Sopenharmony_ci			return -EFAULT;
22838c2ecf20Sopenharmony_ci
22848c2ecf20Sopenharmony_ci		sz = data->branch_stack->nr * sizeof(struct branch_entry);
22858c2ecf20Sopenharmony_ci		if (evsel__has_branch_hw_idx(evsel))
22868c2ecf20Sopenharmony_ci			sz += sizeof(u64);
22878c2ecf20Sopenharmony_ci		else
22888c2ecf20Sopenharmony_ci			data->no_hw_idx = true;
22898c2ecf20Sopenharmony_ci		OVERFLOW_CHECK(array, sz, max_size);
22908c2ecf20Sopenharmony_ci		array = (void *)array + sz;
22918c2ecf20Sopenharmony_ci	}
22928c2ecf20Sopenharmony_ci
22938c2ecf20Sopenharmony_ci	if (type & PERF_SAMPLE_REGS_USER) {
22948c2ecf20Sopenharmony_ci		OVERFLOW_CHECK_u64(array);
22958c2ecf20Sopenharmony_ci		data->user_regs.abi = *array;
22968c2ecf20Sopenharmony_ci		array++;
22978c2ecf20Sopenharmony_ci
22988c2ecf20Sopenharmony_ci		if (data->user_regs.abi) {
22998c2ecf20Sopenharmony_ci			u64 mask = evsel->core.attr.sample_regs_user;
23008c2ecf20Sopenharmony_ci
23018c2ecf20Sopenharmony_ci			sz = hweight64(mask) * sizeof(u64);
23028c2ecf20Sopenharmony_ci			OVERFLOW_CHECK(array, sz, max_size);
23038c2ecf20Sopenharmony_ci			data->user_regs.mask = mask;
23048c2ecf20Sopenharmony_ci			data->user_regs.regs = (u64 *)array;
23058c2ecf20Sopenharmony_ci			array = (void *)array + sz;
23068c2ecf20Sopenharmony_ci		}
23078c2ecf20Sopenharmony_ci	}
23088c2ecf20Sopenharmony_ci
23098c2ecf20Sopenharmony_ci	if (type & PERF_SAMPLE_STACK_USER) {
23108c2ecf20Sopenharmony_ci		OVERFLOW_CHECK_u64(array);
23118c2ecf20Sopenharmony_ci		sz = *array++;
23128c2ecf20Sopenharmony_ci
23138c2ecf20Sopenharmony_ci		data->user_stack.offset = ((char *)(array - 1)
23148c2ecf20Sopenharmony_ci					  - (char *) event);
23158c2ecf20Sopenharmony_ci
23168c2ecf20Sopenharmony_ci		if (!sz) {
23178c2ecf20Sopenharmony_ci			data->user_stack.size = 0;
23188c2ecf20Sopenharmony_ci		} else {
23198c2ecf20Sopenharmony_ci			OVERFLOW_CHECK(array, sz, max_size);
23208c2ecf20Sopenharmony_ci			data->user_stack.data = (char *)array;
23218c2ecf20Sopenharmony_ci			array = (void *)array + sz;
23228c2ecf20Sopenharmony_ci			OVERFLOW_CHECK_u64(array);
23238c2ecf20Sopenharmony_ci			data->user_stack.size = *array++;
23248c2ecf20Sopenharmony_ci			if (WARN_ONCE(data->user_stack.size > sz,
23258c2ecf20Sopenharmony_ci				      "user stack dump failure\n"))
23268c2ecf20Sopenharmony_ci				return -EFAULT;
23278c2ecf20Sopenharmony_ci		}
23288c2ecf20Sopenharmony_ci	}
23298c2ecf20Sopenharmony_ci
23308c2ecf20Sopenharmony_ci	if (type & PERF_SAMPLE_WEIGHT) {
23318c2ecf20Sopenharmony_ci		OVERFLOW_CHECK_u64(array);
23328c2ecf20Sopenharmony_ci		data->weight = *array;
23338c2ecf20Sopenharmony_ci		array++;
23348c2ecf20Sopenharmony_ci	}
23358c2ecf20Sopenharmony_ci
23368c2ecf20Sopenharmony_ci	if (type & PERF_SAMPLE_DATA_SRC) {
23378c2ecf20Sopenharmony_ci		OVERFLOW_CHECK_u64(array);
23388c2ecf20Sopenharmony_ci		data->data_src = *array;
23398c2ecf20Sopenharmony_ci		array++;
23408c2ecf20Sopenharmony_ci	}
23418c2ecf20Sopenharmony_ci
23428c2ecf20Sopenharmony_ci	if (type & PERF_SAMPLE_TRANSACTION) {
23438c2ecf20Sopenharmony_ci		OVERFLOW_CHECK_u64(array);
23448c2ecf20Sopenharmony_ci		data->transaction = *array;
23458c2ecf20Sopenharmony_ci		array++;
23468c2ecf20Sopenharmony_ci	}
23478c2ecf20Sopenharmony_ci
23488c2ecf20Sopenharmony_ci	data->intr_regs.abi = PERF_SAMPLE_REGS_ABI_NONE;
23498c2ecf20Sopenharmony_ci	if (type & PERF_SAMPLE_REGS_INTR) {
23508c2ecf20Sopenharmony_ci		OVERFLOW_CHECK_u64(array);
23518c2ecf20Sopenharmony_ci		data->intr_regs.abi = *array;
23528c2ecf20Sopenharmony_ci		array++;
23538c2ecf20Sopenharmony_ci
23548c2ecf20Sopenharmony_ci		if (data->intr_regs.abi != PERF_SAMPLE_REGS_ABI_NONE) {
23558c2ecf20Sopenharmony_ci			u64 mask = evsel->core.attr.sample_regs_intr;
23568c2ecf20Sopenharmony_ci
23578c2ecf20Sopenharmony_ci			sz = hweight64(mask) * sizeof(u64);
23588c2ecf20Sopenharmony_ci			OVERFLOW_CHECK(array, sz, max_size);
23598c2ecf20Sopenharmony_ci			data->intr_regs.mask = mask;
23608c2ecf20Sopenharmony_ci			data->intr_regs.regs = (u64 *)array;
23618c2ecf20Sopenharmony_ci			array = (void *)array + sz;
23628c2ecf20Sopenharmony_ci		}
23638c2ecf20Sopenharmony_ci	}
23648c2ecf20Sopenharmony_ci
23658c2ecf20Sopenharmony_ci	data->phys_addr = 0;
23668c2ecf20Sopenharmony_ci	if (type & PERF_SAMPLE_PHYS_ADDR) {
23678c2ecf20Sopenharmony_ci		data->phys_addr = *array;
23688c2ecf20Sopenharmony_ci		array++;
23698c2ecf20Sopenharmony_ci	}
23708c2ecf20Sopenharmony_ci
23718c2ecf20Sopenharmony_ci	data->cgroup = 0;
23728c2ecf20Sopenharmony_ci	if (type & PERF_SAMPLE_CGROUP) {
23738c2ecf20Sopenharmony_ci		data->cgroup = *array;
23748c2ecf20Sopenharmony_ci		array++;
23758c2ecf20Sopenharmony_ci	}
23768c2ecf20Sopenharmony_ci
23778c2ecf20Sopenharmony_ci	if (type & PERF_SAMPLE_AUX) {
23788c2ecf20Sopenharmony_ci		OVERFLOW_CHECK_u64(array);
23798c2ecf20Sopenharmony_ci		sz = *array++;
23808c2ecf20Sopenharmony_ci
23818c2ecf20Sopenharmony_ci		OVERFLOW_CHECK(array, sz, max_size);
23828c2ecf20Sopenharmony_ci		/* Undo swap of data */
23838c2ecf20Sopenharmony_ci		if (swapped)
23848c2ecf20Sopenharmony_ci			mem_bswap_64((char *)array, sz);
23858c2ecf20Sopenharmony_ci		data->aux_sample.size = sz;
23868c2ecf20Sopenharmony_ci		data->aux_sample.data = (char *)array;
23878c2ecf20Sopenharmony_ci		array = (void *)array + sz;
23888c2ecf20Sopenharmony_ci	}
23898c2ecf20Sopenharmony_ci
23908c2ecf20Sopenharmony_ci	return 0;
23918c2ecf20Sopenharmony_ci}
23928c2ecf20Sopenharmony_ci
23938c2ecf20Sopenharmony_ciint evsel__parse_sample_timestamp(struct evsel *evsel, union perf_event *event,
23948c2ecf20Sopenharmony_ci				  u64 *timestamp)
23958c2ecf20Sopenharmony_ci{
23968c2ecf20Sopenharmony_ci	u64 type = evsel->core.attr.sample_type;
23978c2ecf20Sopenharmony_ci	const __u64 *array;
23988c2ecf20Sopenharmony_ci
23998c2ecf20Sopenharmony_ci	if (!(type & PERF_SAMPLE_TIME))
24008c2ecf20Sopenharmony_ci		return -1;
24018c2ecf20Sopenharmony_ci
24028c2ecf20Sopenharmony_ci	if (event->header.type != PERF_RECORD_SAMPLE) {
24038c2ecf20Sopenharmony_ci		struct perf_sample data = {
24048c2ecf20Sopenharmony_ci			.time = -1ULL,
24058c2ecf20Sopenharmony_ci		};
24068c2ecf20Sopenharmony_ci
24078c2ecf20Sopenharmony_ci		if (!evsel->core.attr.sample_id_all)
24088c2ecf20Sopenharmony_ci			return -1;
24098c2ecf20Sopenharmony_ci		if (perf_evsel__parse_id_sample(evsel, event, &data))
24108c2ecf20Sopenharmony_ci			return -1;
24118c2ecf20Sopenharmony_ci
24128c2ecf20Sopenharmony_ci		*timestamp = data.time;
24138c2ecf20Sopenharmony_ci		return 0;
24148c2ecf20Sopenharmony_ci	}
24158c2ecf20Sopenharmony_ci
24168c2ecf20Sopenharmony_ci	array = event->sample.array;
24178c2ecf20Sopenharmony_ci
24188c2ecf20Sopenharmony_ci	if (perf_event__check_size(event, evsel->sample_size))
24198c2ecf20Sopenharmony_ci		return -EFAULT;
24208c2ecf20Sopenharmony_ci
24218c2ecf20Sopenharmony_ci	if (type & PERF_SAMPLE_IDENTIFIER)
24228c2ecf20Sopenharmony_ci		array++;
24238c2ecf20Sopenharmony_ci
24248c2ecf20Sopenharmony_ci	if (type & PERF_SAMPLE_IP)
24258c2ecf20Sopenharmony_ci		array++;
24268c2ecf20Sopenharmony_ci
24278c2ecf20Sopenharmony_ci	if (type & PERF_SAMPLE_TID)
24288c2ecf20Sopenharmony_ci		array++;
24298c2ecf20Sopenharmony_ci
24308c2ecf20Sopenharmony_ci	if (type & PERF_SAMPLE_TIME)
24318c2ecf20Sopenharmony_ci		*timestamp = *array;
24328c2ecf20Sopenharmony_ci
24338c2ecf20Sopenharmony_ci	return 0;
24348c2ecf20Sopenharmony_ci}
24358c2ecf20Sopenharmony_ci
24368c2ecf20Sopenharmony_cistruct tep_format_field *evsel__field(struct evsel *evsel, const char *name)
24378c2ecf20Sopenharmony_ci{
24388c2ecf20Sopenharmony_ci	return tep_find_field(evsel->tp_format, name);
24398c2ecf20Sopenharmony_ci}
24408c2ecf20Sopenharmony_ci
24418c2ecf20Sopenharmony_civoid *evsel__rawptr(struct evsel *evsel, struct perf_sample *sample, const char *name)
24428c2ecf20Sopenharmony_ci{
24438c2ecf20Sopenharmony_ci	struct tep_format_field *field = evsel__field(evsel, name);
24448c2ecf20Sopenharmony_ci	int offset;
24458c2ecf20Sopenharmony_ci
24468c2ecf20Sopenharmony_ci	if (!field)
24478c2ecf20Sopenharmony_ci		return NULL;
24488c2ecf20Sopenharmony_ci
24498c2ecf20Sopenharmony_ci	offset = field->offset;
24508c2ecf20Sopenharmony_ci
24518c2ecf20Sopenharmony_ci	if (field->flags & TEP_FIELD_IS_DYNAMIC) {
24528c2ecf20Sopenharmony_ci		offset = *(int *)(sample->raw_data + field->offset);
24538c2ecf20Sopenharmony_ci		offset &= 0xffff;
24548c2ecf20Sopenharmony_ci	}
24558c2ecf20Sopenharmony_ci
24568c2ecf20Sopenharmony_ci	return sample->raw_data + offset;
24578c2ecf20Sopenharmony_ci}
24588c2ecf20Sopenharmony_ci
24598c2ecf20Sopenharmony_ciu64 format_field__intval(struct tep_format_field *field, struct perf_sample *sample,
24608c2ecf20Sopenharmony_ci			 bool needs_swap)
24618c2ecf20Sopenharmony_ci{
24628c2ecf20Sopenharmony_ci	u64 value;
24638c2ecf20Sopenharmony_ci	void *ptr = sample->raw_data + field->offset;
24648c2ecf20Sopenharmony_ci
24658c2ecf20Sopenharmony_ci	switch (field->size) {
24668c2ecf20Sopenharmony_ci	case 1:
24678c2ecf20Sopenharmony_ci		return *(u8 *)ptr;
24688c2ecf20Sopenharmony_ci	case 2:
24698c2ecf20Sopenharmony_ci		value = *(u16 *)ptr;
24708c2ecf20Sopenharmony_ci		break;
24718c2ecf20Sopenharmony_ci	case 4:
24728c2ecf20Sopenharmony_ci		value = *(u32 *)ptr;
24738c2ecf20Sopenharmony_ci		break;
24748c2ecf20Sopenharmony_ci	case 8:
24758c2ecf20Sopenharmony_ci		memcpy(&value, ptr, sizeof(u64));
24768c2ecf20Sopenharmony_ci		break;
24778c2ecf20Sopenharmony_ci	default:
24788c2ecf20Sopenharmony_ci		return 0;
24798c2ecf20Sopenharmony_ci	}
24808c2ecf20Sopenharmony_ci
24818c2ecf20Sopenharmony_ci	if (!needs_swap)
24828c2ecf20Sopenharmony_ci		return value;
24838c2ecf20Sopenharmony_ci
24848c2ecf20Sopenharmony_ci	switch (field->size) {
24858c2ecf20Sopenharmony_ci	case 2:
24868c2ecf20Sopenharmony_ci		return bswap_16(value);
24878c2ecf20Sopenharmony_ci	case 4:
24888c2ecf20Sopenharmony_ci		return bswap_32(value);
24898c2ecf20Sopenharmony_ci	case 8:
24908c2ecf20Sopenharmony_ci		return bswap_64(value);
24918c2ecf20Sopenharmony_ci	default:
24928c2ecf20Sopenharmony_ci		return 0;
24938c2ecf20Sopenharmony_ci	}
24948c2ecf20Sopenharmony_ci
24958c2ecf20Sopenharmony_ci	return 0;
24968c2ecf20Sopenharmony_ci}
24978c2ecf20Sopenharmony_ci
24988c2ecf20Sopenharmony_ciu64 evsel__intval(struct evsel *evsel, struct perf_sample *sample, const char *name)
24998c2ecf20Sopenharmony_ci{
25008c2ecf20Sopenharmony_ci	struct tep_format_field *field = evsel__field(evsel, name);
25018c2ecf20Sopenharmony_ci
25028c2ecf20Sopenharmony_ci	if (!field)
25038c2ecf20Sopenharmony_ci		return 0;
25048c2ecf20Sopenharmony_ci
25058c2ecf20Sopenharmony_ci	return field ? format_field__intval(field, sample, evsel->needs_swap) : 0;
25068c2ecf20Sopenharmony_ci}
25078c2ecf20Sopenharmony_ci
25088c2ecf20Sopenharmony_cibool evsel__fallback(struct evsel *evsel, int err, char *msg, size_t msgsize)
25098c2ecf20Sopenharmony_ci{
25108c2ecf20Sopenharmony_ci	int paranoid;
25118c2ecf20Sopenharmony_ci
25128c2ecf20Sopenharmony_ci	if ((err == ENOENT || err == ENXIO || err == ENODEV) &&
25138c2ecf20Sopenharmony_ci	    evsel->core.attr.type   == PERF_TYPE_HARDWARE &&
25148c2ecf20Sopenharmony_ci	    evsel->core.attr.config == PERF_COUNT_HW_CPU_CYCLES) {
25158c2ecf20Sopenharmony_ci		/*
25168c2ecf20Sopenharmony_ci		 * If it's cycles then fall back to hrtimer based
25178c2ecf20Sopenharmony_ci		 * cpu-clock-tick sw counter, which is always available even if
25188c2ecf20Sopenharmony_ci		 * no PMU support.
25198c2ecf20Sopenharmony_ci		 *
25208c2ecf20Sopenharmony_ci		 * PPC returns ENXIO until 2.6.37 (behavior changed with commit
25218c2ecf20Sopenharmony_ci		 * b0a873e).
25228c2ecf20Sopenharmony_ci		 */
25238c2ecf20Sopenharmony_ci		scnprintf(msg, msgsize, "%s",
25248c2ecf20Sopenharmony_ci"The cycles event is not supported, trying to fall back to cpu-clock-ticks");
25258c2ecf20Sopenharmony_ci
25268c2ecf20Sopenharmony_ci		evsel->core.attr.type   = PERF_TYPE_SOFTWARE;
25278c2ecf20Sopenharmony_ci		evsel->core.attr.config = PERF_COUNT_SW_CPU_CLOCK;
25288c2ecf20Sopenharmony_ci
25298c2ecf20Sopenharmony_ci		zfree(&evsel->name);
25308c2ecf20Sopenharmony_ci		return true;
25318c2ecf20Sopenharmony_ci	} else if (err == EACCES && !evsel->core.attr.exclude_kernel &&
25328c2ecf20Sopenharmony_ci		   (paranoid = perf_event_paranoid()) > 1) {
25338c2ecf20Sopenharmony_ci		const char *name = evsel__name(evsel);
25348c2ecf20Sopenharmony_ci		char *new_name;
25358c2ecf20Sopenharmony_ci		const char *sep = ":";
25368c2ecf20Sopenharmony_ci
25378c2ecf20Sopenharmony_ci		/* If event has exclude user then don't exclude kernel. */
25388c2ecf20Sopenharmony_ci		if (evsel->core.attr.exclude_user)
25398c2ecf20Sopenharmony_ci			return false;
25408c2ecf20Sopenharmony_ci
25418c2ecf20Sopenharmony_ci		/* Is there already the separator in the name. */
25428c2ecf20Sopenharmony_ci		if (strchr(name, '/') ||
25438c2ecf20Sopenharmony_ci		    (strchr(name, ':') && !evsel->is_libpfm_event))
25448c2ecf20Sopenharmony_ci			sep = "";
25458c2ecf20Sopenharmony_ci
25468c2ecf20Sopenharmony_ci		if (asprintf(&new_name, "%s%su", name, sep) < 0)
25478c2ecf20Sopenharmony_ci			return false;
25488c2ecf20Sopenharmony_ci
25498c2ecf20Sopenharmony_ci		if (evsel->name)
25508c2ecf20Sopenharmony_ci			free(evsel->name);
25518c2ecf20Sopenharmony_ci		evsel->name = new_name;
25528c2ecf20Sopenharmony_ci		scnprintf(msg, msgsize, "kernel.perf_event_paranoid=%d, trying "
25538c2ecf20Sopenharmony_ci			  "to fall back to excluding kernel and hypervisor "
25548c2ecf20Sopenharmony_ci			  " samples", paranoid);
25558c2ecf20Sopenharmony_ci		evsel->core.attr.exclude_kernel = 1;
25568c2ecf20Sopenharmony_ci		evsel->core.attr.exclude_hv     = 1;
25578c2ecf20Sopenharmony_ci
25588c2ecf20Sopenharmony_ci		return true;
25598c2ecf20Sopenharmony_ci	}
25608c2ecf20Sopenharmony_ci
25618c2ecf20Sopenharmony_ci	return false;
25628c2ecf20Sopenharmony_ci}
25638c2ecf20Sopenharmony_ci
25648c2ecf20Sopenharmony_cistatic bool find_process(const char *name)
25658c2ecf20Sopenharmony_ci{
25668c2ecf20Sopenharmony_ci	size_t len = strlen(name);
25678c2ecf20Sopenharmony_ci	DIR *dir;
25688c2ecf20Sopenharmony_ci	struct dirent *d;
25698c2ecf20Sopenharmony_ci	int ret = -1;
25708c2ecf20Sopenharmony_ci
25718c2ecf20Sopenharmony_ci	dir = opendir(procfs__mountpoint());
25728c2ecf20Sopenharmony_ci	if (!dir)
25738c2ecf20Sopenharmony_ci		return false;
25748c2ecf20Sopenharmony_ci
25758c2ecf20Sopenharmony_ci	/* Walk through the directory. */
25768c2ecf20Sopenharmony_ci	while (ret && (d = readdir(dir)) != NULL) {
25778c2ecf20Sopenharmony_ci		char path[PATH_MAX];
25788c2ecf20Sopenharmony_ci		char *data;
25798c2ecf20Sopenharmony_ci		size_t size;
25808c2ecf20Sopenharmony_ci
25818c2ecf20Sopenharmony_ci		if ((d->d_type != DT_DIR) ||
25828c2ecf20Sopenharmony_ci		     !strcmp(".", d->d_name) ||
25838c2ecf20Sopenharmony_ci		     !strcmp("..", d->d_name))
25848c2ecf20Sopenharmony_ci			continue;
25858c2ecf20Sopenharmony_ci
25868c2ecf20Sopenharmony_ci		scnprintf(path, sizeof(path), "%s/%s/comm",
25878c2ecf20Sopenharmony_ci			  procfs__mountpoint(), d->d_name);
25888c2ecf20Sopenharmony_ci
25898c2ecf20Sopenharmony_ci		if (filename__read_str(path, &data, &size))
25908c2ecf20Sopenharmony_ci			continue;
25918c2ecf20Sopenharmony_ci
25928c2ecf20Sopenharmony_ci		ret = strncmp(name, data, len);
25938c2ecf20Sopenharmony_ci		free(data);
25948c2ecf20Sopenharmony_ci	}
25958c2ecf20Sopenharmony_ci
25968c2ecf20Sopenharmony_ci	closedir(dir);
25978c2ecf20Sopenharmony_ci	return ret ? false : true;
25988c2ecf20Sopenharmony_ci}
25998c2ecf20Sopenharmony_ci
26008c2ecf20Sopenharmony_ciint evsel__open_strerror(struct evsel *evsel, struct target *target,
26018c2ecf20Sopenharmony_ci			 int err, char *msg, size_t size)
26028c2ecf20Sopenharmony_ci{
26038c2ecf20Sopenharmony_ci	char sbuf[STRERR_BUFSIZE];
26048c2ecf20Sopenharmony_ci	int printed = 0, enforced = 0;
26058c2ecf20Sopenharmony_ci
26068c2ecf20Sopenharmony_ci	switch (err) {
26078c2ecf20Sopenharmony_ci	case EPERM:
26088c2ecf20Sopenharmony_ci	case EACCES:
26098c2ecf20Sopenharmony_ci		printed += scnprintf(msg + printed, size - printed,
26108c2ecf20Sopenharmony_ci			"Access to performance monitoring and observability operations is limited.\n");
26118c2ecf20Sopenharmony_ci
26128c2ecf20Sopenharmony_ci		if (!sysfs__read_int("fs/selinux/enforce", &enforced)) {
26138c2ecf20Sopenharmony_ci			if (enforced) {
26148c2ecf20Sopenharmony_ci				printed += scnprintf(msg + printed, size - printed,
26158c2ecf20Sopenharmony_ci					"Enforced MAC policy settings (SELinux) can limit access to performance\n"
26168c2ecf20Sopenharmony_ci					"monitoring and observability operations. Inspect system audit records for\n"
26178c2ecf20Sopenharmony_ci					"more perf_event access control information and adjusting the policy.\n");
26188c2ecf20Sopenharmony_ci			}
26198c2ecf20Sopenharmony_ci		}
26208c2ecf20Sopenharmony_ci
26218c2ecf20Sopenharmony_ci		if (err == EPERM)
26228c2ecf20Sopenharmony_ci			printed += scnprintf(msg, size,
26238c2ecf20Sopenharmony_ci				"No permission to enable %s event.\n\n", evsel__name(evsel));
26248c2ecf20Sopenharmony_ci
26258c2ecf20Sopenharmony_ci		return scnprintf(msg + printed, size - printed,
26268c2ecf20Sopenharmony_ci		 "Consider adjusting /proc/sys/kernel/perf_event_paranoid setting to open\n"
26278c2ecf20Sopenharmony_ci		 "access to performance monitoring and observability operations for processes\n"
26288c2ecf20Sopenharmony_ci		 "without CAP_PERFMON, CAP_SYS_PTRACE or CAP_SYS_ADMIN Linux capability.\n"
26298c2ecf20Sopenharmony_ci		 "More information can be found at 'Perf events and tool security' document:\n"
26308c2ecf20Sopenharmony_ci		 "https://www.kernel.org/doc/html/latest/admin-guide/perf-security.html\n"
26318c2ecf20Sopenharmony_ci		 "perf_event_paranoid setting is %d:\n"
26328c2ecf20Sopenharmony_ci		 "  -1: Allow use of (almost) all events by all users\n"
26338c2ecf20Sopenharmony_ci		 "      Ignore mlock limit after perf_event_mlock_kb without CAP_IPC_LOCK\n"
26348c2ecf20Sopenharmony_ci		 ">= 0: Disallow raw and ftrace function tracepoint access\n"
26358c2ecf20Sopenharmony_ci		 ">= 1: Disallow CPU event access\n"
26368c2ecf20Sopenharmony_ci		 ">= 2: Disallow kernel profiling\n"
26378c2ecf20Sopenharmony_ci		 "To make the adjusted perf_event_paranoid setting permanent preserve it\n"
26388c2ecf20Sopenharmony_ci		 "in /etc/sysctl.conf (e.g. kernel.perf_event_paranoid = <setting>)",
26398c2ecf20Sopenharmony_ci		 perf_event_paranoid());
26408c2ecf20Sopenharmony_ci	case ENOENT:
26418c2ecf20Sopenharmony_ci		return scnprintf(msg, size, "The %s event is not supported.", evsel__name(evsel));
26428c2ecf20Sopenharmony_ci	case EMFILE:
26438c2ecf20Sopenharmony_ci		return scnprintf(msg, size, "%s",
26448c2ecf20Sopenharmony_ci			 "Too many events are opened.\n"
26458c2ecf20Sopenharmony_ci			 "Probably the maximum number of open file descriptors has been reached.\n"
26468c2ecf20Sopenharmony_ci			 "Hint: Try again after reducing the number of events.\n"
26478c2ecf20Sopenharmony_ci			 "Hint: Try increasing the limit with 'ulimit -n <limit>'");
26488c2ecf20Sopenharmony_ci	case ENOMEM:
26498c2ecf20Sopenharmony_ci		if (evsel__has_callchain(evsel) &&
26508c2ecf20Sopenharmony_ci		    access("/proc/sys/kernel/perf_event_max_stack", F_OK) == 0)
26518c2ecf20Sopenharmony_ci			return scnprintf(msg, size,
26528c2ecf20Sopenharmony_ci					 "Not enough memory to setup event with callchain.\n"
26538c2ecf20Sopenharmony_ci					 "Hint: Try tweaking /proc/sys/kernel/perf_event_max_stack\n"
26548c2ecf20Sopenharmony_ci					 "Hint: Current value: %d", sysctl__max_stack());
26558c2ecf20Sopenharmony_ci		break;
26568c2ecf20Sopenharmony_ci	case ENODEV:
26578c2ecf20Sopenharmony_ci		if (target->cpu_list)
26588c2ecf20Sopenharmony_ci			return scnprintf(msg, size, "%s",
26598c2ecf20Sopenharmony_ci	 "No such device - did you specify an out-of-range profile CPU?");
26608c2ecf20Sopenharmony_ci		break;
26618c2ecf20Sopenharmony_ci	case EOPNOTSUPP:
26628c2ecf20Sopenharmony_ci		if (evsel->core.attr.aux_output)
26638c2ecf20Sopenharmony_ci			return scnprintf(msg, size,
26648c2ecf20Sopenharmony_ci	"%s: PMU Hardware doesn't support 'aux_output' feature",
26658c2ecf20Sopenharmony_ci					 evsel__name(evsel));
26668c2ecf20Sopenharmony_ci		if (evsel->core.attr.sample_period != 0)
26678c2ecf20Sopenharmony_ci			return scnprintf(msg, size,
26688c2ecf20Sopenharmony_ci	"%s: PMU Hardware doesn't support sampling/overflow-interrupts. Try 'perf stat'",
26698c2ecf20Sopenharmony_ci					 evsel__name(evsel));
26708c2ecf20Sopenharmony_ci		if (evsel->core.attr.precise_ip)
26718c2ecf20Sopenharmony_ci			return scnprintf(msg, size, "%s",
26728c2ecf20Sopenharmony_ci	"\'precise\' request may not be supported. Try removing 'p' modifier.");
26738c2ecf20Sopenharmony_ci#if defined(__i386__) || defined(__x86_64__)
26748c2ecf20Sopenharmony_ci		if (evsel->core.attr.type == PERF_TYPE_HARDWARE)
26758c2ecf20Sopenharmony_ci			return scnprintf(msg, size, "%s",
26768c2ecf20Sopenharmony_ci	"No hardware sampling interrupt available.\n");
26778c2ecf20Sopenharmony_ci#endif
26788c2ecf20Sopenharmony_ci		break;
26798c2ecf20Sopenharmony_ci	case EBUSY:
26808c2ecf20Sopenharmony_ci		if (find_process("oprofiled"))
26818c2ecf20Sopenharmony_ci			return scnprintf(msg, size,
26828c2ecf20Sopenharmony_ci	"The PMU counters are busy/taken by another profiler.\n"
26838c2ecf20Sopenharmony_ci	"We found oprofile daemon running, please stop it and try again.");
26848c2ecf20Sopenharmony_ci		break;
26858c2ecf20Sopenharmony_ci	case EINVAL:
26868c2ecf20Sopenharmony_ci		if (evsel->core.attr.write_backward && perf_missing_features.write_backward)
26878c2ecf20Sopenharmony_ci			return scnprintf(msg, size, "Reading from overwrite event is not supported by this kernel.");
26888c2ecf20Sopenharmony_ci		if (perf_missing_features.clockid)
26898c2ecf20Sopenharmony_ci			return scnprintf(msg, size, "clockid feature not supported.");
26908c2ecf20Sopenharmony_ci		if (perf_missing_features.clockid_wrong)
26918c2ecf20Sopenharmony_ci			return scnprintf(msg, size, "wrong clockid (%d).", clockid);
26928c2ecf20Sopenharmony_ci		if (perf_missing_features.aux_output)
26938c2ecf20Sopenharmony_ci			return scnprintf(msg, size, "The 'aux_output' feature is not supported, update the kernel.");
26948c2ecf20Sopenharmony_ci		break;
26958c2ecf20Sopenharmony_ci	default:
26968c2ecf20Sopenharmony_ci		break;
26978c2ecf20Sopenharmony_ci	}
26988c2ecf20Sopenharmony_ci
26998c2ecf20Sopenharmony_ci	return scnprintf(msg, size,
27008c2ecf20Sopenharmony_ci	"The sys_perf_event_open() syscall returned with %d (%s) for event (%s).\n"
27018c2ecf20Sopenharmony_ci	"/bin/dmesg | grep -i perf may provide additional information.\n",
27028c2ecf20Sopenharmony_ci			 err, str_error_r(err, sbuf, sizeof(sbuf)), evsel__name(evsel));
27038c2ecf20Sopenharmony_ci}
27048c2ecf20Sopenharmony_ci
27058c2ecf20Sopenharmony_cistruct perf_env *evsel__env(struct evsel *evsel)
27068c2ecf20Sopenharmony_ci{
27078c2ecf20Sopenharmony_ci	if (evsel && evsel->evlist)
27088c2ecf20Sopenharmony_ci		return evsel->evlist->env;
27098c2ecf20Sopenharmony_ci	return &perf_env;
27108c2ecf20Sopenharmony_ci}
27118c2ecf20Sopenharmony_ci
27128c2ecf20Sopenharmony_cistatic int store_evsel_ids(struct evsel *evsel, struct evlist *evlist)
27138c2ecf20Sopenharmony_ci{
27148c2ecf20Sopenharmony_ci	int cpu, thread;
27158c2ecf20Sopenharmony_ci
27168c2ecf20Sopenharmony_ci	for (cpu = 0; cpu < xyarray__max_x(evsel->core.fd); cpu++) {
27178c2ecf20Sopenharmony_ci		for (thread = 0; thread < xyarray__max_y(evsel->core.fd);
27188c2ecf20Sopenharmony_ci		     thread++) {
27198c2ecf20Sopenharmony_ci			int fd = FD(evsel, cpu, thread);
27208c2ecf20Sopenharmony_ci
27218c2ecf20Sopenharmony_ci			if (perf_evlist__id_add_fd(&evlist->core, &evsel->core,
27228c2ecf20Sopenharmony_ci						   cpu, thread, fd) < 0)
27238c2ecf20Sopenharmony_ci				return -1;
27248c2ecf20Sopenharmony_ci		}
27258c2ecf20Sopenharmony_ci	}
27268c2ecf20Sopenharmony_ci
27278c2ecf20Sopenharmony_ci	return 0;
27288c2ecf20Sopenharmony_ci}
27298c2ecf20Sopenharmony_ci
27308c2ecf20Sopenharmony_ciint evsel__store_ids(struct evsel *evsel, struct evlist *evlist)
27318c2ecf20Sopenharmony_ci{
27328c2ecf20Sopenharmony_ci	struct perf_cpu_map *cpus = evsel->core.cpus;
27338c2ecf20Sopenharmony_ci	struct perf_thread_map *threads = evsel->core.threads;
27348c2ecf20Sopenharmony_ci
27358c2ecf20Sopenharmony_ci	if (perf_evsel__alloc_id(&evsel->core, cpus->nr, threads->nr))
27368c2ecf20Sopenharmony_ci		return -ENOMEM;
27378c2ecf20Sopenharmony_ci
27388c2ecf20Sopenharmony_ci	return store_evsel_ids(evsel, evlist);
27398c2ecf20Sopenharmony_ci}
2740