1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright(C) 2015 Linaro Limited. All rights reserved.
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>
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"
37 struct cs_etm_recording {
38 struct auxtrace_record itr;
39 struct perf_pmu *cs_etm_pmu;
40 struct evlist *evlist;
45 static const char *metadata_etmv3_ro[CS_ETM_PRIV_MAX] = {
46 [CS_ETM_ETMCCER] = "mgmt/etmccer",
47 [CS_ETM_ETMIDR] = "mgmt/etmidr",
50 static const char * const metadata_etmv4_ro[] = {
51 [CS_ETMV4_TRCIDR0] = "trcidr/trcidr0",
52 [CS_ETMV4_TRCIDR1] = "trcidr/trcidr1",
53 [CS_ETMV4_TRCIDR2] = "trcidr/trcidr2",
54 [CS_ETMV4_TRCIDR8] = "trcidr/trcidr8",
55 [CS_ETMV4_TRCAUTHSTATUS] = "mgmt/trcauthstatus",
56 [CS_ETMV4_TS_SOURCE] = "ts_source",
59 static const char * const metadata_ete_ro[] = {
60 [CS_ETE_TRCIDR0] = "trcidr/trcidr0",
61 [CS_ETE_TRCIDR1] = "trcidr/trcidr1",
62 [CS_ETE_TRCIDR2] = "trcidr/trcidr2",
63 [CS_ETE_TRCIDR8] = "trcidr/trcidr8",
64 [CS_ETE_TRCAUTHSTATUS] = "mgmt/trcauthstatus",
65 [CS_ETE_TRCDEVARCH] = "mgmt/trcdevarch",
66 [CS_ETE_TS_SOURCE] = "ts_source",
69 static bool cs_etm_is_etmv4(struct auxtrace_record *itr, int cpu);
70 static bool cs_etm_is_ete(struct auxtrace_record *itr, int cpu);
72 static int cs_etm_validate_context_id(struct auxtrace_record *itr,
73 struct evsel *evsel, int cpu)
75 struct cs_etm_recording *ptr =
76 container_of(itr, struct cs_etm_recording, itr);
77 struct perf_pmu *cs_etm_pmu = ptr->cs_etm_pmu;
82 evsel->core.attr.config &
83 (perf_pmu__format_bits(&cs_etm_pmu->format, "contextid1") |
84 perf_pmu__format_bits(&cs_etm_pmu->format, "contextid2"));
89 /* Not supported in etmv3 */
90 if (!cs_etm_is_etmv4(itr, cpu)) {
91 pr_err("%s: contextid not supported in ETMv3, disable with %s/contextid=0/\n",
92 CORESIGHT_ETM_PMU_NAME, CORESIGHT_ETM_PMU_NAME);
96 /* Get a handle on TRCIDR2 */
97 snprintf(path, PATH_MAX, "cpu%d/%s",
98 cpu, metadata_etmv4_ro[CS_ETMV4_TRCIDR2]);
99 err = perf_pmu__scan_file(cs_etm_pmu, path, "%x", &val);
101 /* There was a problem reading the file, bailing out */
103 pr_err("%s: can't read file %s\n", CORESIGHT_ETM_PMU_NAME,
109 perf_pmu__format_bits(&cs_etm_pmu->format, "contextid1")) {
111 * TRCIDR2.CIDSIZE, bit [9-5], indicates whether contextID
112 * tracing is supported:
113 * 0b00000 Context ID tracing is not supported.
114 * 0b00100 Maximum of 32-bit Context ID size.
115 * All other values are reserved.
117 val = BMVAL(val, 5, 9);
118 if (!val || val != 0x4) {
119 pr_err("%s: CONTEXTIDR_EL1 isn't supported, disable with %s/contextid1=0/\n",
120 CORESIGHT_ETM_PMU_NAME, CORESIGHT_ETM_PMU_NAME);
126 perf_pmu__format_bits(&cs_etm_pmu->format, "contextid2")) {
128 * TRCIDR2.VMIDOPT[30:29] != 0 and
129 * TRCIDR2.VMIDSIZE[14:10] == 0b00100 (32bit virtual contextid)
130 * We can't support CONTEXTIDR in VMID if the size of the
131 * virtual context id is < 32bit.
132 * Any value of VMIDSIZE >= 4 (i.e, > 32bit) is fine for us.
134 if (!BMVAL(val, 29, 30) || BMVAL(val, 10, 14) < 4) {
135 pr_err("%s: CONTEXTIDR_EL2 isn't supported, disable with %s/contextid2=0/\n",
136 CORESIGHT_ETM_PMU_NAME, CORESIGHT_ETM_PMU_NAME);
144 static int cs_etm_validate_timestamp(struct auxtrace_record *itr,
145 struct evsel *evsel, int cpu)
147 struct cs_etm_recording *ptr =
148 container_of(itr, struct cs_etm_recording, itr);
149 struct perf_pmu *cs_etm_pmu = ptr->cs_etm_pmu;
154 if (!(evsel->core.attr.config &
155 perf_pmu__format_bits(&cs_etm_pmu->format, "timestamp")))
158 if (!cs_etm_is_etmv4(itr, cpu)) {
159 pr_err("%s: timestamp not supported in ETMv3, disable with %s/timestamp=0/\n",
160 CORESIGHT_ETM_PMU_NAME, CORESIGHT_ETM_PMU_NAME);
164 /* Get a handle on TRCIRD0 */
165 snprintf(path, PATH_MAX, "cpu%d/%s",
166 cpu, metadata_etmv4_ro[CS_ETMV4_TRCIDR0]);
167 err = perf_pmu__scan_file(cs_etm_pmu, path, "%x", &val);
169 /* There was a problem reading the file, bailing out */
171 pr_err("%s: can't read file %s\n",
172 CORESIGHT_ETM_PMU_NAME, path);
177 * TRCIDR0.TSSIZE, bit [28-24], indicates whether global timestamping
179 * 0b00000 Global timestamping is not implemented
180 * 0b00110 Implementation supports a maximum timestamp of 48bits.
181 * 0b01000 Implementation supports a maximum timestamp of 64bits.
183 val &= GENMASK(28, 24);
192 * Check whether the requested timestamp and contextid options should be
193 * available on all requested CPUs and if not, tell the user how to override.
194 * The kernel will silently disable any unavailable options so a warning here
195 * first is better. In theory the kernel could still disable the option for
196 * some other reason so this is best effort only.
198 static int cs_etm_validate_config(struct auxtrace_record *itr,
201 int i, err = -EINVAL;
202 struct perf_cpu_map *event_cpus = evsel->evlist->core.user_requested_cpus;
203 struct perf_cpu_map *online_cpus = perf_cpu_map__new(NULL);
205 /* Set option of each CPU we have */
206 for (i = 0; i < cpu__max_cpu().cpu; i++) {
207 struct perf_cpu cpu = { .cpu = i, };
209 if (!perf_cpu_map__has(event_cpus, cpu) ||
210 !perf_cpu_map__has(online_cpus, cpu))
213 err = cs_etm_validate_context_id(itr, evsel, i);
216 err = cs_etm_validate_timestamp(itr, evsel, i);
223 perf_cpu_map__put(online_cpus);
227 static int cs_etm_parse_snapshot_options(struct auxtrace_record *itr,
228 struct record_opts *opts,
231 struct cs_etm_recording *ptr =
232 container_of(itr, struct cs_etm_recording, itr);
233 unsigned long long snapshot_size = 0;
237 snapshot_size = strtoull(str, &endptr, 0);
238 if (*endptr || snapshot_size > SIZE_MAX)
242 opts->auxtrace_snapshot_mode = true;
243 opts->auxtrace_snapshot_size = snapshot_size;
244 ptr->snapshot_size = snapshot_size;
249 static int cs_etm_set_sink_attr(struct perf_pmu *pmu,
252 char msg[BUFSIZ], path[PATH_MAX], *sink;
253 struct evsel_config_term *term;
257 if (evsel->core.attr.config2 & GENMASK(31, 0))
260 list_for_each_entry(term, &evsel->config_terms, list) {
261 if (term->type != EVSEL__CONFIG_TERM_DRV_CFG)
264 sink = term->val.str;
265 snprintf(path, PATH_MAX, "sinks/%s", sink);
267 ret = perf_pmu__scan_file(pmu, path, "%x", &hash);
270 pr_err("Couldn't find sink \"%s\" on event %s\n"
271 "Missing kernel or device support?\n\n"
272 "Hint: An appropriate sink will be picked automatically if one isn't specified.\n",
273 sink, evsel__name(evsel));
275 pr_err("Failed to set sink \"%s\" on event %s with %d (%s)\n",
276 sink, evsel__name(evsel), errno,
277 str_error_r(errno, msg, sizeof(msg)));
281 evsel->core.attr.config2 |= hash;
286 * No sink was provided on the command line - allow the CoreSight
287 * system to look for a default
292 static int cs_etm_recording_options(struct auxtrace_record *itr,
293 struct evlist *evlist,
294 struct record_opts *opts)
297 struct cs_etm_recording *ptr =
298 container_of(itr, struct cs_etm_recording, itr);
299 struct perf_pmu *cs_etm_pmu = ptr->cs_etm_pmu;
300 struct evsel *evsel, *cs_etm_evsel = NULL;
301 struct perf_cpu_map *cpus = evlist->core.user_requested_cpus;
302 bool privileged = perf_event_paranoid_check(-1);
305 evlist__for_each_entry(evlist, evsel) {
306 if (evsel->core.attr.type == cs_etm_pmu->type) {
308 pr_err("There may be only one %s event\n",
309 CORESIGHT_ETM_PMU_NAME);
312 cs_etm_evsel = evsel;
316 /* no need to continue if at least one event of interest was found */
320 ptr->evlist = evlist;
321 ptr->snapshot_mode = opts->auxtrace_snapshot_mode;
323 if (!record_opts__no_switch_events(opts) &&
324 perf_can_record_switch_events())
325 opts->record_switch_events = true;
327 cs_etm_evsel->needs_auxtrace_mmap = true;
328 opts->full_auxtrace = true;
330 ret = cs_etm_set_sink_attr(cs_etm_pmu, cs_etm_evsel);
334 if (opts->use_clockid) {
335 pr_err("Cannot use clockid (-k option) with %s\n",
336 CORESIGHT_ETM_PMU_NAME);
340 /* we are in snapshot mode */
341 if (opts->auxtrace_snapshot_mode) {
343 * No size were given to '-S' or '-m,', so go with
346 if (!opts->auxtrace_snapshot_size &&
347 !opts->auxtrace_mmap_pages) {
349 opts->auxtrace_mmap_pages = MiB(4) / page_size;
351 opts->auxtrace_mmap_pages =
352 KiB(128) / page_size;
353 if (opts->mmap_pages == UINT_MAX)
354 opts->mmap_pages = KiB(256) / page_size;
356 } else if (!opts->auxtrace_mmap_pages && !privileged &&
357 opts->mmap_pages == UINT_MAX) {
358 opts->mmap_pages = KiB(256) / page_size;
362 * '-m,xyz' was specified but no snapshot size, so make the
363 * snapshot size as big as the auxtrace mmap area.
365 if (!opts->auxtrace_snapshot_size) {
366 opts->auxtrace_snapshot_size =
367 opts->auxtrace_mmap_pages * (size_t)page_size;
371 * -Sxyz was specified but no auxtrace mmap area, so make the
372 * auxtrace mmap area big enough to fit the requested snapshot
375 if (!opts->auxtrace_mmap_pages) {
376 size_t sz = opts->auxtrace_snapshot_size;
378 sz = round_up(sz, page_size) / page_size;
379 opts->auxtrace_mmap_pages = roundup_pow_of_two(sz);
382 /* Snapshot size can't be bigger than the auxtrace area */
383 if (opts->auxtrace_snapshot_size >
384 opts->auxtrace_mmap_pages * (size_t)page_size) {
385 pr_err("Snapshot size %zu must not be greater than AUX area tracing mmap size %zu\n",
386 opts->auxtrace_snapshot_size,
387 opts->auxtrace_mmap_pages * (size_t)page_size);
391 /* Something went wrong somewhere - this shouldn't happen */
392 if (!opts->auxtrace_snapshot_size ||
393 !opts->auxtrace_mmap_pages) {
394 pr_err("Failed to calculate default snapshot size and/or AUX area tracing mmap pages\n");
399 /* Buffer sizes weren't specified with '-m,xyz' so give some defaults */
400 if (!opts->auxtrace_mmap_pages) {
402 opts->auxtrace_mmap_pages = MiB(4) / page_size;
404 opts->auxtrace_mmap_pages = KiB(128) / page_size;
405 if (opts->mmap_pages == UINT_MAX)
406 opts->mmap_pages = KiB(256) / page_size;
410 if (opts->auxtrace_snapshot_mode)
411 pr_debug2("%s snapshot size: %zu\n", CORESIGHT_ETM_PMU_NAME,
412 opts->auxtrace_snapshot_size);
415 * To obtain the auxtrace buffer file descriptor, the auxtrace
416 * event must come first.
418 evlist__to_front(evlist, cs_etm_evsel);
421 * get the CPU on the sample - need it to associate trace ID in the
422 * AUX_OUTPUT_HW_ID event, and the AUX event for per-cpu mmaps.
424 evsel__set_sample_bit(cs_etm_evsel, CPU);
427 * Also the case of per-cpu mmaps, need the contextID in order to be notified
428 * when a context switch happened.
430 if (!perf_cpu_map__empty(cpus)) {
431 evsel__set_config_if_unset(cs_etm_pmu, cs_etm_evsel,
433 evsel__set_config_if_unset(cs_etm_pmu, cs_etm_evsel,
437 /* Add dummy event to keep tracking */
438 err = parse_event(evlist, "dummy:u");
441 evsel = evlist__last(evlist);
442 evlist__set_tracking_event(evlist, evsel);
443 evsel->core.attr.freq = 0;
444 evsel->core.attr.sample_period = 1;
446 /* In per-cpu case, always need the time of mmap events etc */
447 if (!perf_cpu_map__empty(cpus))
448 evsel__set_sample_bit(evsel, TIME);
450 err = cs_etm_validate_config(itr, cs_etm_evsel);
455 static u64 cs_etm_get_config(struct auxtrace_record *itr)
458 struct cs_etm_recording *ptr =
459 container_of(itr, struct cs_etm_recording, itr);
460 struct perf_pmu *cs_etm_pmu = ptr->cs_etm_pmu;
461 struct evlist *evlist = ptr->evlist;
464 evlist__for_each_entry(evlist, evsel) {
465 if (evsel->core.attr.type == cs_etm_pmu->type) {
467 * Variable perf_event_attr::config is assigned to
468 * ETMv3/PTM. The bit fields have been made to match
469 * the ETMv3.5 ETRMCR register specification. See the
470 * PMU_FORMAT_ATTR() declarations in
471 * drivers/hwtracing/coresight/coresight-perf.c for
474 config = evsel->core.attr.config;
483 #define BIT(N) (1UL << (N))
486 static u64 cs_etmv4_get_config(struct auxtrace_record *itr)
492 * The perf event variable config bits represent both
493 * the command line options and register programming
494 * bits in ETMv3/PTM. For ETMv4 we must remap options
497 config_opts = cs_etm_get_config(itr);
498 if (config_opts & BIT(ETM_OPT_CYCACC))
499 config |= BIT(ETM4_CFG_BIT_CYCACC);
500 if (config_opts & BIT(ETM_OPT_CTXTID))
501 config |= BIT(ETM4_CFG_BIT_CTXTID);
502 if (config_opts & BIT(ETM_OPT_TS))
503 config |= BIT(ETM4_CFG_BIT_TS);
504 if (config_opts & BIT(ETM_OPT_RETSTK))
505 config |= BIT(ETM4_CFG_BIT_RETSTK);
506 if (config_opts & BIT(ETM_OPT_CTXTID2))
507 config |= BIT(ETM4_CFG_BIT_VMID) |
508 BIT(ETM4_CFG_BIT_VMID_OPT);
509 if (config_opts & BIT(ETM_OPT_BRANCH_BROADCAST))
510 config |= BIT(ETM4_CFG_BIT_BB);
516 cs_etm_info_priv_size(struct auxtrace_record *itr __maybe_unused,
517 struct evlist *evlist __maybe_unused)
520 int etmv3 = 0, etmv4 = 0, ete = 0;
521 struct perf_cpu_map *event_cpus = evlist->core.user_requested_cpus;
522 struct perf_cpu_map *online_cpus = perf_cpu_map__new(NULL);
524 /* cpu map is not empty, we have specific CPUs to work with */
525 if (!perf_cpu_map__empty(event_cpus)) {
526 for (i = 0; i < cpu__max_cpu().cpu; i++) {
527 struct perf_cpu cpu = { .cpu = i, };
529 if (!perf_cpu_map__has(event_cpus, cpu) ||
530 !perf_cpu_map__has(online_cpus, cpu))
533 if (cs_etm_is_ete(itr, i))
535 else if (cs_etm_is_etmv4(itr, i))
541 /* get configuration for all CPUs in the system */
542 for (i = 0; i < cpu__max_cpu().cpu; i++) {
543 struct perf_cpu cpu = { .cpu = i, };
545 if (!perf_cpu_map__has(online_cpus, cpu))
548 if (cs_etm_is_ete(itr, i))
550 else if (cs_etm_is_etmv4(itr, i))
557 perf_cpu_map__put(online_cpus);
559 return (CS_ETM_HEADER_SIZE +
560 (ete * CS_ETE_PRIV_SIZE) +
561 (etmv4 * CS_ETMV4_PRIV_SIZE) +
562 (etmv3 * CS_ETMV3_PRIV_SIZE));
565 static bool cs_etm_is_etmv4(struct auxtrace_record *itr, int cpu)
571 struct cs_etm_recording *ptr =
572 container_of(itr, struct cs_etm_recording, itr);
573 struct perf_pmu *cs_etm_pmu = ptr->cs_etm_pmu;
575 /* Take any of the RO files for ETMv4 and see if it present */
576 snprintf(path, PATH_MAX, "cpu%d/%s",
577 cpu, metadata_etmv4_ro[CS_ETMV4_TRCIDR0]);
578 scan = perf_pmu__scan_file(cs_etm_pmu, path, "%x", &val);
580 /* The file was read successfully, we have a winner */
587 static int cs_etm_get_ro(struct perf_pmu *pmu, int cpu, const char *path)
589 char pmu_path[PATH_MAX];
591 unsigned int val = 0;
593 /* Get RO metadata from sysfs */
594 snprintf(pmu_path, PATH_MAX, "cpu%d/%s", cpu, path);
596 scan = perf_pmu__scan_file(pmu, pmu_path, "%x", &val);
598 pr_err("%s: error reading: %s\n", __func__, pmu_path);
603 static int cs_etm_get_ro_signed(struct perf_pmu *pmu, int cpu, const char *path)
605 char pmu_path[PATH_MAX];
609 /* Get RO metadata from sysfs */
610 snprintf(pmu_path, PATH_MAX, "cpu%d/%s", cpu, path);
612 scan = perf_pmu__scan_file(pmu, pmu_path, "%d", &val);
614 pr_err("%s: error reading: %s\n", __func__, pmu_path);
619 static bool cs_etm_pmu_path_exists(struct perf_pmu *pmu, int cpu, const char *path)
621 char pmu_path[PATH_MAX];
623 /* Get RO metadata from sysfs */
624 snprintf(pmu_path, PATH_MAX, "cpu%d/%s", cpu, path);
626 return perf_pmu__file_exists(pmu, pmu_path);
629 #define TRCDEVARCH_ARCHPART_SHIFT 0
630 #define TRCDEVARCH_ARCHPART_MASK GENMASK(11, 0)
631 #define TRCDEVARCH_ARCHPART(x) (((x) & TRCDEVARCH_ARCHPART_MASK) >> TRCDEVARCH_ARCHPART_SHIFT)
633 #define TRCDEVARCH_ARCHVER_SHIFT 12
634 #define TRCDEVARCH_ARCHVER_MASK GENMASK(15, 12)
635 #define TRCDEVARCH_ARCHVER(x) (((x) & TRCDEVARCH_ARCHVER_MASK) >> TRCDEVARCH_ARCHVER_SHIFT)
637 static bool cs_etm_is_ete(struct auxtrace_record *itr, int cpu)
639 struct cs_etm_recording *ptr = container_of(itr, struct cs_etm_recording, itr);
640 struct perf_pmu *cs_etm_pmu = ptr->cs_etm_pmu;
643 if (!cs_etm_pmu_path_exists(cs_etm_pmu, cpu, metadata_ete_ro[CS_ETE_TRCDEVARCH]))
646 trcdevarch = cs_etm_get_ro(cs_etm_pmu, cpu, metadata_ete_ro[CS_ETE_TRCDEVARCH]);
648 * ETE if ARCHVER is 5 (ARCHVER is 4 for ETM) and ARCHPART is 0xA13.
649 * See ETM_DEVARCH_ETE_ARCH in coresight-etm4x.h
651 return TRCDEVARCH_ARCHVER(trcdevarch) == 5 && TRCDEVARCH_ARCHPART(trcdevarch) == 0xA13;
654 static void cs_etm_save_etmv4_header(__u64 data[], struct auxtrace_record *itr, int cpu)
656 struct cs_etm_recording *ptr = container_of(itr, struct cs_etm_recording, itr);
657 struct perf_pmu *cs_etm_pmu = ptr->cs_etm_pmu;
659 /* Get trace configuration register */
660 data[CS_ETMV4_TRCCONFIGR] = cs_etmv4_get_config(itr);
661 /* traceID set to legacy version, in case new perf running on older system */
662 data[CS_ETMV4_TRCTRACEIDR] =
663 CORESIGHT_LEGACY_CPU_TRACE_ID(cpu) | CORESIGHT_TRACE_ID_UNUSED_FLAG;
665 /* Get read-only information from sysFS */
666 data[CS_ETMV4_TRCIDR0] = cs_etm_get_ro(cs_etm_pmu, cpu,
667 metadata_etmv4_ro[CS_ETMV4_TRCIDR0]);
668 data[CS_ETMV4_TRCIDR1] = cs_etm_get_ro(cs_etm_pmu, cpu,
669 metadata_etmv4_ro[CS_ETMV4_TRCIDR1]);
670 data[CS_ETMV4_TRCIDR2] = cs_etm_get_ro(cs_etm_pmu, cpu,
671 metadata_etmv4_ro[CS_ETMV4_TRCIDR2]);
672 data[CS_ETMV4_TRCIDR8] = cs_etm_get_ro(cs_etm_pmu, cpu,
673 metadata_etmv4_ro[CS_ETMV4_TRCIDR8]);
674 data[CS_ETMV4_TRCAUTHSTATUS] = cs_etm_get_ro(cs_etm_pmu, cpu,
675 metadata_etmv4_ro[CS_ETMV4_TRCAUTHSTATUS]);
677 /* Kernels older than 5.19 may not expose ts_source */
678 if (cs_etm_pmu_path_exists(cs_etm_pmu, cpu, metadata_etmv4_ro[CS_ETMV4_TS_SOURCE]))
679 data[CS_ETMV4_TS_SOURCE] = (__u64) cs_etm_get_ro_signed(cs_etm_pmu, cpu,
680 metadata_etmv4_ro[CS_ETMV4_TS_SOURCE]);
682 pr_debug3("[%03d] pmu file 'ts_source' not found. Fallback to safe value (-1)\n",
684 data[CS_ETMV4_TS_SOURCE] = (__u64) -1;
688 static void cs_etm_save_ete_header(__u64 data[], struct auxtrace_record *itr, int cpu)
690 struct cs_etm_recording *ptr = container_of(itr, struct cs_etm_recording, itr);
691 struct perf_pmu *cs_etm_pmu = ptr->cs_etm_pmu;
693 /* Get trace configuration register */
694 data[CS_ETE_TRCCONFIGR] = cs_etmv4_get_config(itr);
695 /* traceID set to legacy version, in case new perf running on older system */
696 data[CS_ETE_TRCTRACEIDR] =
697 CORESIGHT_LEGACY_CPU_TRACE_ID(cpu) | CORESIGHT_TRACE_ID_UNUSED_FLAG;
699 /* Get read-only information from sysFS */
700 data[CS_ETE_TRCIDR0] = cs_etm_get_ro(cs_etm_pmu, cpu,
701 metadata_ete_ro[CS_ETE_TRCIDR0]);
702 data[CS_ETE_TRCIDR1] = cs_etm_get_ro(cs_etm_pmu, cpu,
703 metadata_ete_ro[CS_ETE_TRCIDR1]);
704 data[CS_ETE_TRCIDR2] = cs_etm_get_ro(cs_etm_pmu, cpu,
705 metadata_ete_ro[CS_ETE_TRCIDR2]);
706 data[CS_ETE_TRCIDR8] = cs_etm_get_ro(cs_etm_pmu, cpu,
707 metadata_ete_ro[CS_ETE_TRCIDR8]);
708 data[CS_ETE_TRCAUTHSTATUS] = cs_etm_get_ro(cs_etm_pmu, cpu,
709 metadata_ete_ro[CS_ETE_TRCAUTHSTATUS]);
710 /* ETE uses the same registers as ETMv4 plus TRCDEVARCH */
711 data[CS_ETE_TRCDEVARCH] = cs_etm_get_ro(cs_etm_pmu, cpu,
712 metadata_ete_ro[CS_ETE_TRCDEVARCH]);
714 /* Kernels older than 5.19 may not expose ts_source */
715 if (cs_etm_pmu_path_exists(cs_etm_pmu, cpu, metadata_ete_ro[CS_ETE_TS_SOURCE]))
716 data[CS_ETE_TS_SOURCE] = (__u64) cs_etm_get_ro_signed(cs_etm_pmu, cpu,
717 metadata_ete_ro[CS_ETE_TS_SOURCE]);
719 pr_debug3("[%03d] pmu file 'ts_source' not found. Fallback to safe value (-1)\n",
721 data[CS_ETE_TS_SOURCE] = (__u64) -1;
725 static void cs_etm_get_metadata(int cpu, u32 *offset,
726 struct auxtrace_record *itr,
727 struct perf_record_auxtrace_info *info)
729 u32 increment, nr_trc_params;
731 struct cs_etm_recording *ptr =
732 container_of(itr, struct cs_etm_recording, itr);
733 struct perf_pmu *cs_etm_pmu = ptr->cs_etm_pmu;
735 /* first see what kind of tracer this cpu is affined to */
736 if (cs_etm_is_ete(itr, cpu)) {
737 magic = __perf_cs_ete_magic;
738 cs_etm_save_ete_header(&info->priv[*offset], itr, cpu);
740 /* How much space was used */
741 increment = CS_ETE_PRIV_MAX;
742 nr_trc_params = CS_ETE_PRIV_MAX - CS_ETM_COMMON_BLK_MAX_V1;
743 } else if (cs_etm_is_etmv4(itr, cpu)) {
744 magic = __perf_cs_etmv4_magic;
745 cs_etm_save_etmv4_header(&info->priv[*offset], itr, cpu);
747 /* How much space was used */
748 increment = CS_ETMV4_PRIV_MAX;
749 nr_trc_params = CS_ETMV4_PRIV_MAX - CS_ETMV4_TRCCONFIGR;
751 magic = __perf_cs_etmv3_magic;
752 /* Get configuration register */
753 info->priv[*offset + CS_ETM_ETMCR] = cs_etm_get_config(itr);
754 /* traceID set to legacy value in case new perf running on old system */
755 info->priv[*offset + CS_ETM_ETMTRACEIDR] =
756 CORESIGHT_LEGACY_CPU_TRACE_ID(cpu) | CORESIGHT_TRACE_ID_UNUSED_FLAG;
757 /* Get read-only information from sysFS */
758 info->priv[*offset + CS_ETM_ETMCCER] =
759 cs_etm_get_ro(cs_etm_pmu, cpu,
760 metadata_etmv3_ro[CS_ETM_ETMCCER]);
761 info->priv[*offset + CS_ETM_ETMIDR] =
762 cs_etm_get_ro(cs_etm_pmu, cpu,
763 metadata_etmv3_ro[CS_ETM_ETMIDR]);
765 /* How much space was used */
766 increment = CS_ETM_PRIV_MAX;
767 nr_trc_params = CS_ETM_PRIV_MAX - CS_ETM_ETMCR;
770 /* Build generic header portion */
771 info->priv[*offset + CS_ETM_MAGIC] = magic;
772 info->priv[*offset + CS_ETM_CPU] = cpu;
773 info->priv[*offset + CS_ETM_NR_TRC_PARAMS] = nr_trc_params;
774 /* Where the next CPU entry should start from */
775 *offset += increment;
778 static int cs_etm_info_fill(struct auxtrace_record *itr,
779 struct perf_session *session,
780 struct perf_record_auxtrace_info *info,
786 struct perf_cpu_map *cpu_map;
787 struct perf_cpu_map *event_cpus = session->evlist->core.user_requested_cpus;
788 struct perf_cpu_map *online_cpus = perf_cpu_map__new(NULL);
789 struct cs_etm_recording *ptr =
790 container_of(itr, struct cs_etm_recording, itr);
791 struct perf_pmu *cs_etm_pmu = ptr->cs_etm_pmu;
793 if (priv_size != cs_etm_info_priv_size(itr, session->evlist))
796 if (!session->evlist->core.nr_mmaps)
799 /* If the cpu_map is empty all online CPUs are involved */
800 if (perf_cpu_map__empty(event_cpus)) {
801 cpu_map = online_cpus;
803 /* Make sure all specified CPUs are online */
804 for (i = 0; i < perf_cpu_map__nr(event_cpus); i++) {
805 struct perf_cpu cpu = { .cpu = i, };
807 if (perf_cpu_map__has(event_cpus, cpu) &&
808 !perf_cpu_map__has(online_cpus, cpu))
812 cpu_map = event_cpus;
815 nr_cpu = perf_cpu_map__nr(cpu_map);
816 /* Get PMU type as dynamically assigned by the core */
817 type = cs_etm_pmu->type;
819 /* First fill out the session header */
820 info->type = PERF_AUXTRACE_CS_ETM;
821 info->priv[CS_HEADER_VERSION] = CS_HEADER_CURRENT_VERSION;
822 info->priv[CS_PMU_TYPE_CPUS] = type << 32;
823 info->priv[CS_PMU_TYPE_CPUS] |= nr_cpu;
824 info->priv[CS_ETM_SNAPSHOT] = ptr->snapshot_mode;
826 offset = CS_ETM_SNAPSHOT + 1;
828 for (i = 0; i < cpu__max_cpu().cpu && offset < priv_size; i++) {
829 struct perf_cpu cpu = { .cpu = i, };
831 if (perf_cpu_map__has(cpu_map, cpu))
832 cs_etm_get_metadata(i, &offset, itr, info);
835 perf_cpu_map__put(online_cpus);
840 static int cs_etm_snapshot_start(struct auxtrace_record *itr)
842 struct cs_etm_recording *ptr =
843 container_of(itr, struct cs_etm_recording, itr);
846 evlist__for_each_entry(ptr->evlist, evsel) {
847 if (evsel->core.attr.type == ptr->cs_etm_pmu->type)
848 return evsel__disable(evsel);
853 static int cs_etm_snapshot_finish(struct auxtrace_record *itr)
855 struct cs_etm_recording *ptr =
856 container_of(itr, struct cs_etm_recording, itr);
859 evlist__for_each_entry(ptr->evlist, evsel) {
860 if (evsel->core.attr.type == ptr->cs_etm_pmu->type)
861 return evsel__enable(evsel);
866 static u64 cs_etm_reference(struct auxtrace_record *itr __maybe_unused)
868 return (((u64) rand() << 0) & 0x00000000FFFFFFFFull) |
869 (((u64) rand() << 32) & 0xFFFFFFFF00000000ull);
872 static void cs_etm_recording_free(struct auxtrace_record *itr)
874 struct cs_etm_recording *ptr =
875 container_of(itr, struct cs_etm_recording, itr);
880 struct auxtrace_record *cs_etm_record_init(int *err)
882 struct perf_pmu *cs_etm_pmu;
883 struct cs_etm_recording *ptr;
885 cs_etm_pmu = perf_pmu__find(CORESIGHT_ETM_PMU_NAME);
892 ptr = zalloc(sizeof(struct cs_etm_recording));
898 ptr->cs_etm_pmu = cs_etm_pmu;
899 ptr->itr.pmu = cs_etm_pmu;
900 ptr->itr.parse_snapshot_options = cs_etm_parse_snapshot_options;
901 ptr->itr.recording_options = cs_etm_recording_options;
902 ptr->itr.info_priv_size = cs_etm_info_priv_size;
903 ptr->itr.info_fill = cs_etm_info_fill;
904 ptr->itr.snapshot_start = cs_etm_snapshot_start;
905 ptr->itr.snapshot_finish = cs_etm_snapshot_finish;
906 ptr->itr.reference = cs_etm_reference;
907 ptr->itr.free = cs_etm_recording_free;
908 ptr->itr.read_finish = auxtrace_record__read_finish;
917 * Set a default config to enable the user changed config tracking mechanism
918 * (CFG_CHG and evsel__set_config_if_unset()). If no default is set then user
919 * changes aren't tracked.
921 struct perf_event_attr *
922 cs_etm_get_default_config(struct perf_pmu *pmu __maybe_unused)
924 struct perf_event_attr *attr;
926 attr = zalloc(sizeof(struct perf_event_attr));
930 attr->sample_period = 1;