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