xref: /openbmc/linux/tools/perf/arch/arm/util/cs-etm.c (revision 9ac17575)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright(C) 2015 Linaro Limited. All rights reserved.
4  * Author: Mathieu Poirier <mathieu.poirier@linaro.org>
5  */
6 
7 #include <api/fs/fs.h>
8 #include <linux/bits.h>
9 #include <linux/bitops.h>
10 #include <linux/compiler.h>
11 #include <linux/coresight-pmu.h>
12 #include <linux/kernel.h>
13 #include <linux/log2.h>
14 #include <linux/string.h>
15 #include <linux/types.h>
16 #include <linux/zalloc.h>
17 
18 #include "cs-etm.h"
19 #include "../../util/debug.h"
20 #include "../../util/record.h"
21 #include "../../util/auxtrace.h"
22 #include "../../util/cpumap.h"
23 #include "../../util/event.h"
24 #include "../../util/evlist.h"
25 #include "../../util/evsel.h"
26 #include "../../util/perf_api_probe.h"
27 #include "../../util/evsel_config.h"
28 #include "../../util/pmu.h"
29 #include "../../util/cs-etm.h"
30 #include <internal/lib.h> // page_size
31 #include "../../util/session.h"
32 
33 #include <errno.h>
34 #include <stdlib.h>
35 #include <sys/stat.h>
36 
37 struct cs_etm_recording {
38 	struct auxtrace_record	itr;
39 	struct perf_pmu		*cs_etm_pmu;
40 	struct evlist		*evlist;
41 	int			wrapped_cnt;
42 	bool			*wrapped;
43 	bool			snapshot_mode;
44 	size_t			snapshot_size;
45 };
46 
47 static const char *metadata_etmv3_ro[CS_ETM_PRIV_MAX] = {
48 	[CS_ETM_ETMCCER]	= "mgmt/etmccer",
49 	[CS_ETM_ETMIDR]		= "mgmt/etmidr",
50 };
51 
52 static const char *metadata_etmv4_ro[CS_ETMV4_PRIV_MAX] = {
53 	[CS_ETMV4_TRCIDR0]		= "trcidr/trcidr0",
54 	[CS_ETMV4_TRCIDR1]		= "trcidr/trcidr1",
55 	[CS_ETMV4_TRCIDR2]		= "trcidr/trcidr2",
56 	[CS_ETMV4_TRCIDR8]		= "trcidr/trcidr8",
57 	[CS_ETMV4_TRCAUTHSTATUS]	= "mgmt/trcauthstatus",
58 };
59 
60 static bool cs_etm_is_etmv4(struct auxtrace_record *itr, int cpu);
61 
62 static int cs_etm_set_context_id(struct auxtrace_record *itr,
63 				 struct evsel *evsel, int cpu)
64 {
65 	struct cs_etm_recording *ptr;
66 	struct perf_pmu *cs_etm_pmu;
67 	char path[PATH_MAX];
68 	int err = -EINVAL;
69 	u32 val;
70 
71 	ptr = container_of(itr, struct cs_etm_recording, itr);
72 	cs_etm_pmu = ptr->cs_etm_pmu;
73 
74 	if (!cs_etm_is_etmv4(itr, cpu))
75 		goto out;
76 
77 	/* Get a handle on TRCIRD2 */
78 	snprintf(path, PATH_MAX, "cpu%d/%s",
79 		 cpu, metadata_etmv4_ro[CS_ETMV4_TRCIDR2]);
80 	err = perf_pmu__scan_file(cs_etm_pmu, path, "%x", &val);
81 
82 	/* There was a problem reading the file, bailing out */
83 	if (err != 1) {
84 		pr_err("%s: can't read file %s\n",
85 		       CORESIGHT_ETM_PMU_NAME, path);
86 		goto out;
87 	}
88 
89 	/*
90 	 * TRCIDR2.CIDSIZE, bit [9-5], indicates whether contextID tracing
91 	 * is supported:
92 	 *  0b00000 Context ID tracing is not supported.
93 	 *  0b00100 Maximum of 32-bit Context ID size.
94 	 *  All other values are reserved.
95 	 */
96 	val = BMVAL(val, 5, 9);
97 	if (!val || val != 0x4) {
98 		err = -EINVAL;
99 		goto out;
100 	}
101 
102 	/* All good, let the kernel know */
103 	evsel->core.attr.config |= (1 << ETM_OPT_CTXTID);
104 	err = 0;
105 
106 out:
107 
108 	return err;
109 }
110 
111 static int cs_etm_set_timestamp(struct auxtrace_record *itr,
112 				struct evsel *evsel, int cpu)
113 {
114 	struct cs_etm_recording *ptr;
115 	struct perf_pmu *cs_etm_pmu;
116 	char path[PATH_MAX];
117 	int err = -EINVAL;
118 	u32 val;
119 
120 	ptr = container_of(itr, struct cs_etm_recording, itr);
121 	cs_etm_pmu = ptr->cs_etm_pmu;
122 
123 	if (!cs_etm_is_etmv4(itr, cpu))
124 		goto out;
125 
126 	/* Get a handle on TRCIRD0 */
127 	snprintf(path, PATH_MAX, "cpu%d/%s",
128 		 cpu, metadata_etmv4_ro[CS_ETMV4_TRCIDR0]);
129 	err = perf_pmu__scan_file(cs_etm_pmu, path, "%x", &val);
130 
131 	/* There was a problem reading the file, bailing out */
132 	if (err != 1) {
133 		pr_err("%s: can't read file %s\n",
134 		       CORESIGHT_ETM_PMU_NAME, path);
135 		goto out;
136 	}
137 
138 	/*
139 	 * TRCIDR0.TSSIZE, bit [28-24], indicates whether global timestamping
140 	 * is supported:
141 	 *  0b00000 Global timestamping is not implemented
142 	 *  0b00110 Implementation supports a maximum timestamp of 48bits.
143 	 *  0b01000 Implementation supports a maximum timestamp of 64bits.
144 	 */
145 	val &= GENMASK(28, 24);
146 	if (!val) {
147 		err = -EINVAL;
148 		goto out;
149 	}
150 
151 	/* All good, let the kernel know */
152 	evsel->core.attr.config |= (1 << ETM_OPT_TS);
153 	err = 0;
154 
155 out:
156 	return err;
157 }
158 
159 static int cs_etm_set_option(struct auxtrace_record *itr,
160 			     struct evsel *evsel, u32 option)
161 {
162 	int i, err = -EINVAL;
163 	struct perf_cpu_map *event_cpus = evsel->evlist->core.cpus;
164 	struct perf_cpu_map *online_cpus = perf_cpu_map__new(NULL);
165 
166 	/* Set option of each CPU we have */
167 	for (i = 0; i < cpu__max_cpu(); i++) {
168 		if (!cpu_map__has(event_cpus, i) ||
169 		    !cpu_map__has(online_cpus, i))
170 			continue;
171 
172 		if (option & ETM_OPT_CTXTID) {
173 			err = cs_etm_set_context_id(itr, evsel, i);
174 			if (err)
175 				goto out;
176 		}
177 		if (option & ETM_OPT_TS) {
178 			err = cs_etm_set_timestamp(itr, evsel, i);
179 			if (err)
180 				goto out;
181 		}
182 		if (option & ~(ETM_OPT_CTXTID | ETM_OPT_TS))
183 			/* Nothing else is currently supported */
184 			goto out;
185 	}
186 
187 	err = 0;
188 out:
189 	perf_cpu_map__put(online_cpus);
190 	return err;
191 }
192 
193 static int cs_etm_parse_snapshot_options(struct auxtrace_record *itr,
194 					 struct record_opts *opts,
195 					 const char *str)
196 {
197 	struct cs_etm_recording *ptr =
198 				container_of(itr, struct cs_etm_recording, itr);
199 	unsigned long long snapshot_size = 0;
200 	char *endptr;
201 
202 	if (str) {
203 		snapshot_size = strtoull(str, &endptr, 0);
204 		if (*endptr || snapshot_size > SIZE_MAX)
205 			return -1;
206 	}
207 
208 	opts->auxtrace_snapshot_mode = true;
209 	opts->auxtrace_snapshot_size = snapshot_size;
210 	ptr->snapshot_size = snapshot_size;
211 
212 	return 0;
213 }
214 
215 static int cs_etm_set_sink_attr(struct perf_pmu *pmu,
216 				struct evsel *evsel)
217 {
218 	char msg[BUFSIZ], path[PATH_MAX], *sink;
219 	struct perf_evsel_config_term *term;
220 	int ret = -EINVAL;
221 	u32 hash;
222 
223 	if (evsel->core.attr.config2 & GENMASK(31, 0))
224 		return 0;
225 
226 	list_for_each_entry(term, &evsel->config_terms, list) {
227 		if (term->type != PERF_EVSEL__CONFIG_TERM_DRV_CFG)
228 			continue;
229 
230 		sink = term->val.str;
231 		snprintf(path, PATH_MAX, "sinks/%s", sink);
232 
233 		ret = perf_pmu__scan_file(pmu, path, "%x", &hash);
234 		if (ret != 1) {
235 			pr_err("failed to set sink \"%s\" on event %s with %d (%s)\n",
236 			       sink, evsel__name(evsel), errno,
237 			       str_error_r(errno, msg, sizeof(msg)));
238 			return ret;
239 		}
240 
241 		evsel->core.attr.config2 |= hash;
242 		return 0;
243 	}
244 
245 	/*
246 	 * No sink was provided on the command line - for _now_ treat
247 	 * this as an error.
248 	 */
249 	return ret;
250 }
251 
252 static int cs_etm_recording_options(struct auxtrace_record *itr,
253 				    struct evlist *evlist,
254 				    struct record_opts *opts)
255 {
256 	int ret;
257 	struct cs_etm_recording *ptr =
258 				container_of(itr, struct cs_etm_recording, itr);
259 	struct perf_pmu *cs_etm_pmu = ptr->cs_etm_pmu;
260 	struct evsel *evsel, *cs_etm_evsel = NULL;
261 	struct perf_cpu_map *cpus = evlist->core.cpus;
262 	bool privileged = perf_event_paranoid_check(-1);
263 	int err = 0;
264 
265 	ptr->evlist = evlist;
266 	ptr->snapshot_mode = opts->auxtrace_snapshot_mode;
267 
268 	if (perf_can_record_switch_events())
269 		opts->record_switch_events = true;
270 
271 	evlist__for_each_entry(evlist, evsel) {
272 		if (evsel->core.attr.type == cs_etm_pmu->type) {
273 			if (cs_etm_evsel) {
274 				pr_err("There may be only one %s event\n",
275 				       CORESIGHT_ETM_PMU_NAME);
276 				return -EINVAL;
277 			}
278 			evsel->core.attr.freq = 0;
279 			evsel->core.attr.sample_period = 1;
280 			cs_etm_evsel = evsel;
281 			opts->full_auxtrace = true;
282 		}
283 	}
284 
285 	/* no need to continue if at least one event of interest was found */
286 	if (!cs_etm_evsel)
287 		return 0;
288 
289 	ret = cs_etm_set_sink_attr(cs_etm_pmu, cs_etm_evsel);
290 	if (ret)
291 		return ret;
292 
293 	if (opts->use_clockid) {
294 		pr_err("Cannot use clockid (-k option) with %s\n",
295 		       CORESIGHT_ETM_PMU_NAME);
296 		return -EINVAL;
297 	}
298 
299 	/* we are in snapshot mode */
300 	if (opts->auxtrace_snapshot_mode) {
301 		/*
302 		 * No size were given to '-S' or '-m,', so go with
303 		 * the default
304 		 */
305 		if (!opts->auxtrace_snapshot_size &&
306 		    !opts->auxtrace_mmap_pages) {
307 			if (privileged) {
308 				opts->auxtrace_mmap_pages = MiB(4) / page_size;
309 			} else {
310 				opts->auxtrace_mmap_pages =
311 							KiB(128) / page_size;
312 				if (opts->mmap_pages == UINT_MAX)
313 					opts->mmap_pages = KiB(256) / page_size;
314 			}
315 		} else if (!opts->auxtrace_mmap_pages && !privileged &&
316 						opts->mmap_pages == UINT_MAX) {
317 			opts->mmap_pages = KiB(256) / page_size;
318 		}
319 
320 		/*
321 		 * '-m,xyz' was specified but no snapshot size, so make the
322 		 * snapshot size as big as the auxtrace mmap area.
323 		 */
324 		if (!opts->auxtrace_snapshot_size) {
325 			opts->auxtrace_snapshot_size =
326 				opts->auxtrace_mmap_pages * (size_t)page_size;
327 		}
328 
329 		/*
330 		 * -Sxyz was specified but no auxtrace mmap area, so make the
331 		 * auxtrace mmap area big enough to fit the requested snapshot
332 		 * size.
333 		 */
334 		if (!opts->auxtrace_mmap_pages) {
335 			size_t sz = opts->auxtrace_snapshot_size;
336 
337 			sz = round_up(sz, page_size) / page_size;
338 			opts->auxtrace_mmap_pages = roundup_pow_of_two(sz);
339 		}
340 
341 		/* Snapshost size can't be bigger than the auxtrace area */
342 		if (opts->auxtrace_snapshot_size >
343 				opts->auxtrace_mmap_pages * (size_t)page_size) {
344 			pr_err("Snapshot size %zu must not be greater than AUX area tracing mmap size %zu\n",
345 			       opts->auxtrace_snapshot_size,
346 			       opts->auxtrace_mmap_pages * (size_t)page_size);
347 			return -EINVAL;
348 		}
349 
350 		/* Something went wrong somewhere - this shouldn't happen */
351 		if (!opts->auxtrace_snapshot_size ||
352 		    !opts->auxtrace_mmap_pages) {
353 			pr_err("Failed to calculate default snapshot size and/or AUX area tracing mmap pages\n");
354 			return -EINVAL;
355 		}
356 	}
357 
358 	/* We are in full trace mode but '-m,xyz' wasn't specified */
359 	if (opts->full_auxtrace && !opts->auxtrace_mmap_pages) {
360 		if (privileged) {
361 			opts->auxtrace_mmap_pages = MiB(4) / page_size;
362 		} else {
363 			opts->auxtrace_mmap_pages = KiB(128) / page_size;
364 			if (opts->mmap_pages == UINT_MAX)
365 				opts->mmap_pages = KiB(256) / page_size;
366 		}
367 
368 	}
369 
370 	/* Validate auxtrace_mmap_pages provided by user */
371 	if (opts->auxtrace_mmap_pages) {
372 		unsigned int max_page = (KiB(128) / page_size);
373 		size_t sz = opts->auxtrace_mmap_pages * (size_t)page_size;
374 
375 		if (!privileged &&
376 		    opts->auxtrace_mmap_pages > max_page) {
377 			opts->auxtrace_mmap_pages = max_page;
378 			pr_err("auxtrace too big, truncating to %d\n",
379 			       max_page);
380 		}
381 
382 		if (!is_power_of_2(sz)) {
383 			pr_err("Invalid mmap size for %s: must be a power of 2\n",
384 			       CORESIGHT_ETM_PMU_NAME);
385 			return -EINVAL;
386 		}
387 	}
388 
389 	if (opts->auxtrace_snapshot_mode)
390 		pr_debug2("%s snapshot size: %zu\n", CORESIGHT_ETM_PMU_NAME,
391 			  opts->auxtrace_snapshot_size);
392 
393 	/*
394 	 * To obtain the auxtrace buffer file descriptor, the auxtrace
395 	 * event must come first.
396 	 */
397 	perf_evlist__to_front(evlist, cs_etm_evsel);
398 
399 	/*
400 	 * In the case of per-cpu mmaps, we need the CPU on the
401 	 * AUX event.  We also need the contextID in order to be notified
402 	 * when a context switch happened.
403 	 */
404 	if (!perf_cpu_map__empty(cpus)) {
405 		evsel__set_sample_bit(cs_etm_evsel, CPU);
406 
407 		err = cs_etm_set_option(itr, cs_etm_evsel,
408 					ETM_OPT_CTXTID | ETM_OPT_TS);
409 		if (err)
410 			goto out;
411 	}
412 
413 	/* Add dummy event to keep tracking */
414 	if (opts->full_auxtrace) {
415 		struct evsel *tracking_evsel;
416 
417 		err = parse_events(evlist, "dummy:u", NULL);
418 		if (err)
419 			goto out;
420 
421 		tracking_evsel = evlist__last(evlist);
422 		perf_evlist__set_tracking_event(evlist, tracking_evsel);
423 
424 		tracking_evsel->core.attr.freq = 0;
425 		tracking_evsel->core.attr.sample_period = 1;
426 
427 		/* In per-cpu case, always need the time of mmap events etc */
428 		if (!perf_cpu_map__empty(cpus))
429 			evsel__set_sample_bit(tracking_evsel, TIME);
430 	}
431 
432 out:
433 	return err;
434 }
435 
436 static u64 cs_etm_get_config(struct auxtrace_record *itr)
437 {
438 	u64 config = 0;
439 	struct cs_etm_recording *ptr =
440 			container_of(itr, struct cs_etm_recording, itr);
441 	struct perf_pmu *cs_etm_pmu = ptr->cs_etm_pmu;
442 	struct evlist *evlist = ptr->evlist;
443 	struct evsel *evsel;
444 
445 	evlist__for_each_entry(evlist, evsel) {
446 		if (evsel->core.attr.type == cs_etm_pmu->type) {
447 			/*
448 			 * Variable perf_event_attr::config is assigned to
449 			 * ETMv3/PTM.  The bit fields have been made to match
450 			 * the ETMv3.5 ETRMCR register specification.  See the
451 			 * PMU_FORMAT_ATTR() declarations in
452 			 * drivers/hwtracing/coresight/coresight-perf.c for
453 			 * details.
454 			 */
455 			config = evsel->core.attr.config;
456 			break;
457 		}
458 	}
459 
460 	return config;
461 }
462 
463 #ifndef BIT
464 #define BIT(N) (1UL << (N))
465 #endif
466 
467 static u64 cs_etmv4_get_config(struct auxtrace_record *itr)
468 {
469 	u64 config = 0;
470 	u64 config_opts = 0;
471 
472 	/*
473 	 * The perf event variable config bits represent both
474 	 * the command line options and register programming
475 	 * bits in ETMv3/PTM. For ETMv4 we must remap options
476 	 * to real bits
477 	 */
478 	config_opts = cs_etm_get_config(itr);
479 	if (config_opts & BIT(ETM_OPT_CYCACC))
480 		config |= BIT(ETM4_CFG_BIT_CYCACC);
481 	if (config_opts & BIT(ETM_OPT_CTXTID))
482 		config |= BIT(ETM4_CFG_BIT_CTXTID);
483 	if (config_opts & BIT(ETM_OPT_TS))
484 		config |= BIT(ETM4_CFG_BIT_TS);
485 	if (config_opts & BIT(ETM_OPT_RETSTK))
486 		config |= BIT(ETM4_CFG_BIT_RETSTK);
487 
488 	return config;
489 }
490 
491 static size_t
492 cs_etm_info_priv_size(struct auxtrace_record *itr __maybe_unused,
493 		      struct evlist *evlist __maybe_unused)
494 {
495 	int i;
496 	int etmv3 = 0, etmv4 = 0;
497 	struct perf_cpu_map *event_cpus = evlist->core.cpus;
498 	struct perf_cpu_map *online_cpus = perf_cpu_map__new(NULL);
499 
500 	/* cpu map is not empty, we have specific CPUs to work with */
501 	if (!perf_cpu_map__empty(event_cpus)) {
502 		for (i = 0; i < cpu__max_cpu(); i++) {
503 			if (!cpu_map__has(event_cpus, i) ||
504 			    !cpu_map__has(online_cpus, i))
505 				continue;
506 
507 			if (cs_etm_is_etmv4(itr, i))
508 				etmv4++;
509 			else
510 				etmv3++;
511 		}
512 	} else {
513 		/* get configuration for all CPUs in the system */
514 		for (i = 0; i < cpu__max_cpu(); i++) {
515 			if (!cpu_map__has(online_cpus, i))
516 				continue;
517 
518 			if (cs_etm_is_etmv4(itr, i))
519 				etmv4++;
520 			else
521 				etmv3++;
522 		}
523 	}
524 
525 	perf_cpu_map__put(online_cpus);
526 
527 	return (CS_ETM_HEADER_SIZE +
528 	       (etmv4 * CS_ETMV4_PRIV_SIZE) +
529 	       (etmv3 * CS_ETMV3_PRIV_SIZE));
530 }
531 
532 static bool cs_etm_is_etmv4(struct auxtrace_record *itr, int cpu)
533 {
534 	bool ret = false;
535 	char path[PATH_MAX];
536 	int scan;
537 	unsigned int val;
538 	struct cs_etm_recording *ptr =
539 			container_of(itr, struct cs_etm_recording, itr);
540 	struct perf_pmu *cs_etm_pmu = ptr->cs_etm_pmu;
541 
542 	/* Take any of the RO files for ETMv4 and see if it present */
543 	snprintf(path, PATH_MAX, "cpu%d/%s",
544 		 cpu, metadata_etmv4_ro[CS_ETMV4_TRCIDR0]);
545 	scan = perf_pmu__scan_file(cs_etm_pmu, path, "%x", &val);
546 
547 	/* The file was read successfully, we have a winner */
548 	if (scan == 1)
549 		ret = true;
550 
551 	return ret;
552 }
553 
554 static int cs_etm_get_ro(struct perf_pmu *pmu, int cpu, const char *path)
555 {
556 	char pmu_path[PATH_MAX];
557 	int scan;
558 	unsigned int val = 0;
559 
560 	/* Get RO metadata from sysfs */
561 	snprintf(pmu_path, PATH_MAX, "cpu%d/%s", cpu, path);
562 
563 	scan = perf_pmu__scan_file(pmu, pmu_path, "%x", &val);
564 	if (scan != 1)
565 		pr_err("%s: error reading: %s\n", __func__, pmu_path);
566 
567 	return val;
568 }
569 
570 static void cs_etm_get_metadata(int cpu, u32 *offset,
571 				struct auxtrace_record *itr,
572 				struct perf_record_auxtrace_info *info)
573 {
574 	u32 increment;
575 	u64 magic;
576 	struct cs_etm_recording *ptr =
577 			container_of(itr, struct cs_etm_recording, itr);
578 	struct perf_pmu *cs_etm_pmu = ptr->cs_etm_pmu;
579 
580 	/* first see what kind of tracer this cpu is affined to */
581 	if (cs_etm_is_etmv4(itr, cpu)) {
582 		magic = __perf_cs_etmv4_magic;
583 		/* Get trace configuration register */
584 		info->priv[*offset + CS_ETMV4_TRCCONFIGR] =
585 						cs_etmv4_get_config(itr);
586 		/* Get traceID from the framework */
587 		info->priv[*offset + CS_ETMV4_TRCTRACEIDR] =
588 						coresight_get_trace_id(cpu);
589 		/* Get read-only information from sysFS */
590 		info->priv[*offset + CS_ETMV4_TRCIDR0] =
591 			cs_etm_get_ro(cs_etm_pmu, cpu,
592 				      metadata_etmv4_ro[CS_ETMV4_TRCIDR0]);
593 		info->priv[*offset + CS_ETMV4_TRCIDR1] =
594 			cs_etm_get_ro(cs_etm_pmu, cpu,
595 				      metadata_etmv4_ro[CS_ETMV4_TRCIDR1]);
596 		info->priv[*offset + CS_ETMV4_TRCIDR2] =
597 			cs_etm_get_ro(cs_etm_pmu, cpu,
598 				      metadata_etmv4_ro[CS_ETMV4_TRCIDR2]);
599 		info->priv[*offset + CS_ETMV4_TRCIDR8] =
600 			cs_etm_get_ro(cs_etm_pmu, cpu,
601 				      metadata_etmv4_ro[CS_ETMV4_TRCIDR8]);
602 		info->priv[*offset + CS_ETMV4_TRCAUTHSTATUS] =
603 			cs_etm_get_ro(cs_etm_pmu, cpu,
604 				      metadata_etmv4_ro
605 				      [CS_ETMV4_TRCAUTHSTATUS]);
606 
607 		/* How much space was used */
608 		increment = CS_ETMV4_PRIV_MAX;
609 	} else {
610 		magic = __perf_cs_etmv3_magic;
611 		/* Get configuration register */
612 		info->priv[*offset + CS_ETM_ETMCR] = cs_etm_get_config(itr);
613 		/* Get traceID from the framework */
614 		info->priv[*offset + CS_ETM_ETMTRACEIDR] =
615 						coresight_get_trace_id(cpu);
616 		/* Get read-only information from sysFS */
617 		info->priv[*offset + CS_ETM_ETMCCER] =
618 			cs_etm_get_ro(cs_etm_pmu, cpu,
619 				      metadata_etmv3_ro[CS_ETM_ETMCCER]);
620 		info->priv[*offset + CS_ETM_ETMIDR] =
621 			cs_etm_get_ro(cs_etm_pmu, cpu,
622 				      metadata_etmv3_ro[CS_ETM_ETMIDR]);
623 
624 		/* How much space was used */
625 		increment = CS_ETM_PRIV_MAX;
626 	}
627 
628 	/* Build generic header portion */
629 	info->priv[*offset + CS_ETM_MAGIC] = magic;
630 	info->priv[*offset + CS_ETM_CPU] = cpu;
631 	/* Where the next CPU entry should start from */
632 	*offset += increment;
633 }
634 
635 static int cs_etm_info_fill(struct auxtrace_record *itr,
636 			    struct perf_session *session,
637 			    struct perf_record_auxtrace_info *info,
638 			    size_t priv_size)
639 {
640 	int i;
641 	u32 offset;
642 	u64 nr_cpu, type;
643 	struct perf_cpu_map *cpu_map;
644 	struct perf_cpu_map *event_cpus = session->evlist->core.cpus;
645 	struct perf_cpu_map *online_cpus = perf_cpu_map__new(NULL);
646 	struct cs_etm_recording *ptr =
647 			container_of(itr, struct cs_etm_recording, itr);
648 	struct perf_pmu *cs_etm_pmu = ptr->cs_etm_pmu;
649 
650 	if (priv_size != cs_etm_info_priv_size(itr, session->evlist))
651 		return -EINVAL;
652 
653 	if (!session->evlist->core.nr_mmaps)
654 		return -EINVAL;
655 
656 	/* If the cpu_map is empty all online CPUs are involved */
657 	if (perf_cpu_map__empty(event_cpus)) {
658 		cpu_map = online_cpus;
659 	} else {
660 		/* Make sure all specified CPUs are online */
661 		for (i = 0; i < perf_cpu_map__nr(event_cpus); i++) {
662 			if (cpu_map__has(event_cpus, i) &&
663 			    !cpu_map__has(online_cpus, i))
664 				return -EINVAL;
665 		}
666 
667 		cpu_map = event_cpus;
668 	}
669 
670 	nr_cpu = perf_cpu_map__nr(cpu_map);
671 	/* Get PMU type as dynamically assigned by the core */
672 	type = cs_etm_pmu->type;
673 
674 	/* First fill out the session header */
675 	info->type = PERF_AUXTRACE_CS_ETM;
676 	info->priv[CS_HEADER_VERSION_0] = 0;
677 	info->priv[CS_PMU_TYPE_CPUS] = type << 32;
678 	info->priv[CS_PMU_TYPE_CPUS] |= nr_cpu;
679 	info->priv[CS_ETM_SNAPSHOT] = ptr->snapshot_mode;
680 
681 	offset = CS_ETM_SNAPSHOT + 1;
682 
683 	for (i = 0; i < cpu__max_cpu() && offset < priv_size; i++)
684 		if (cpu_map__has(cpu_map, i))
685 			cs_etm_get_metadata(i, &offset, itr, info);
686 
687 	perf_cpu_map__put(online_cpus);
688 
689 	return 0;
690 }
691 
692 static int cs_etm_alloc_wrapped_array(struct cs_etm_recording *ptr, int idx)
693 {
694 	bool *wrapped;
695 	int cnt = ptr->wrapped_cnt;
696 
697 	/* Make @ptr->wrapped as big as @idx */
698 	while (cnt <= idx)
699 		cnt++;
700 
701 	/*
702 	 * Free'ed in cs_etm_recording_free().  Using realloc() to avoid
703 	 * cross compilation problems where the host's system supports
704 	 * reallocarray() but not the target.
705 	 */
706 	wrapped = realloc(ptr->wrapped, cnt * sizeof(bool));
707 	if (!wrapped)
708 		return -ENOMEM;
709 
710 	wrapped[cnt - 1] = false;
711 	ptr->wrapped_cnt = cnt;
712 	ptr->wrapped = wrapped;
713 
714 	return 0;
715 }
716 
717 static bool cs_etm_buffer_has_wrapped(unsigned char *buffer,
718 				      size_t buffer_size, u64 head)
719 {
720 	u64 i, watermark;
721 	u64 *buf = (u64 *)buffer;
722 	size_t buf_size = buffer_size;
723 
724 	/*
725 	 * We want to look the very last 512 byte (chosen arbitrarily) in
726 	 * the ring buffer.
727 	 */
728 	watermark = buf_size - 512;
729 
730 	/*
731 	 * @head is continuously increasing - if its value is equal or greater
732 	 * than the size of the ring buffer, it has wrapped around.
733 	 */
734 	if (head >= buffer_size)
735 		return true;
736 
737 	/*
738 	 * The value of @head is somewhere within the size of the ring buffer.
739 	 * This can be that there hasn't been enough data to fill the ring
740 	 * buffer yet or the trace time was so long that @head has numerically
741 	 * wrapped around.  To find we need to check if we have data at the very
742 	 * end of the ring buffer.  We can reliably do this because mmap'ed
743 	 * pages are zeroed out and there is a fresh mapping with every new
744 	 * session.
745 	 */
746 
747 	/* @head is less than 512 byte from the end of the ring buffer */
748 	if (head > watermark)
749 		watermark = head;
750 
751 	/*
752 	 * Speed things up by using 64 bit transactions (see "u64 *buf" above)
753 	 */
754 	watermark >>= 3;
755 	buf_size >>= 3;
756 
757 	/*
758 	 * If we find trace data at the end of the ring buffer, @head has
759 	 * been there and has numerically wrapped around at least once.
760 	 */
761 	for (i = watermark; i < buf_size; i++)
762 		if (buf[i])
763 			return true;
764 
765 	return false;
766 }
767 
768 static int cs_etm_find_snapshot(struct auxtrace_record *itr,
769 				int idx, struct auxtrace_mmap *mm,
770 				unsigned char *data,
771 				u64 *head, u64 *old)
772 {
773 	int err;
774 	bool wrapped;
775 	struct cs_etm_recording *ptr =
776 			container_of(itr, struct cs_etm_recording, itr);
777 
778 	/*
779 	 * Allocate memory to keep track of wrapping if this is the first
780 	 * time we deal with this *mm.
781 	 */
782 	if (idx >= ptr->wrapped_cnt) {
783 		err = cs_etm_alloc_wrapped_array(ptr, idx);
784 		if (err)
785 			return err;
786 	}
787 
788 	/*
789 	 * Check to see if *head has wrapped around.  If it hasn't only the
790 	 * amount of data between *head and *old is snapshot'ed to avoid
791 	 * bloating the perf.data file with zeros.  But as soon as *head has
792 	 * wrapped around the entire size of the AUX ring buffer it taken.
793 	 */
794 	wrapped = ptr->wrapped[idx];
795 	if (!wrapped && cs_etm_buffer_has_wrapped(data, mm->len, *head)) {
796 		wrapped = true;
797 		ptr->wrapped[idx] = true;
798 	}
799 
800 	pr_debug3("%s: mmap index %d old head %zu new head %zu size %zu\n",
801 		  __func__, idx, (size_t)*old, (size_t)*head, mm->len);
802 
803 	/* No wrap has occurred, we can just use *head and *old. */
804 	if (!wrapped)
805 		return 0;
806 
807 	/*
808 	 * *head has wrapped around - adjust *head and *old to pickup the
809 	 * entire content of the AUX buffer.
810 	 */
811 	if (*head >= mm->len) {
812 		*old = *head - mm->len;
813 	} else {
814 		*head += mm->len;
815 		*old = *head - mm->len;
816 	}
817 
818 	return 0;
819 }
820 
821 static int cs_etm_snapshot_start(struct auxtrace_record *itr)
822 {
823 	struct cs_etm_recording *ptr =
824 			container_of(itr, struct cs_etm_recording, itr);
825 	struct evsel *evsel;
826 
827 	evlist__for_each_entry(ptr->evlist, evsel) {
828 		if (evsel->core.attr.type == ptr->cs_etm_pmu->type)
829 			return evsel__disable(evsel);
830 	}
831 	return -EINVAL;
832 }
833 
834 static int cs_etm_snapshot_finish(struct auxtrace_record *itr)
835 {
836 	struct cs_etm_recording *ptr =
837 			container_of(itr, struct cs_etm_recording, itr);
838 	struct evsel *evsel;
839 
840 	evlist__for_each_entry(ptr->evlist, evsel) {
841 		if (evsel->core.attr.type == ptr->cs_etm_pmu->type)
842 			return evsel__enable(evsel);
843 	}
844 	return -EINVAL;
845 }
846 
847 static u64 cs_etm_reference(struct auxtrace_record *itr __maybe_unused)
848 {
849 	return (((u64) rand() <<  0) & 0x00000000FFFFFFFFull) |
850 		(((u64) rand() << 32) & 0xFFFFFFFF00000000ull);
851 }
852 
853 static void cs_etm_recording_free(struct auxtrace_record *itr)
854 {
855 	struct cs_etm_recording *ptr =
856 			container_of(itr, struct cs_etm_recording, itr);
857 
858 	zfree(&ptr->wrapped);
859 	free(ptr);
860 }
861 
862 struct auxtrace_record *cs_etm_record_init(int *err)
863 {
864 	struct perf_pmu *cs_etm_pmu;
865 	struct cs_etm_recording *ptr;
866 
867 	cs_etm_pmu = perf_pmu__find(CORESIGHT_ETM_PMU_NAME);
868 
869 	if (!cs_etm_pmu) {
870 		*err = -EINVAL;
871 		goto out;
872 	}
873 
874 	ptr = zalloc(sizeof(struct cs_etm_recording));
875 	if (!ptr) {
876 		*err = -ENOMEM;
877 		goto out;
878 	}
879 
880 	ptr->cs_etm_pmu			= cs_etm_pmu;
881 	ptr->itr.pmu			= cs_etm_pmu;
882 	ptr->itr.parse_snapshot_options	= cs_etm_parse_snapshot_options;
883 	ptr->itr.recording_options	= cs_etm_recording_options;
884 	ptr->itr.info_priv_size		= cs_etm_info_priv_size;
885 	ptr->itr.info_fill		= cs_etm_info_fill;
886 	ptr->itr.find_snapshot		= cs_etm_find_snapshot;
887 	ptr->itr.snapshot_start		= cs_etm_snapshot_start;
888 	ptr->itr.snapshot_finish	= cs_etm_snapshot_finish;
889 	ptr->itr.reference		= cs_etm_reference;
890 	ptr->itr.free			= cs_etm_recording_free;
891 	ptr->itr.read_finish		= auxtrace_record__read_finish;
892 
893 	*err = 0;
894 	return &ptr->itr;
895 out:
896 	return NULL;
897 }
898