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/pmus.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 bool snapshot_mode; 42 size_t snapshot_size; 43 }; 44 45 static const char *metadata_etmv3_ro[CS_ETM_PRIV_MAX] = { 46 [CS_ETM_ETMCCER] = "mgmt/etmccer", 47 [CS_ETM_ETMIDR] = "mgmt/etmidr", 48 }; 49 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", 57 }; 58 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", 67 }; 68 69 enum cs_etm_version { CS_NOT_PRESENT, CS_ETMV3, CS_ETMV4, CS_ETE }; 70 71 /* ETMv4 CONFIGR register bits */ 72 #define TRCCONFIGR_BB BIT(3) 73 #define TRCCONFIGR_CCI BIT(4) 74 #define TRCCONFIGR_CID BIT(6) 75 #define TRCCONFIGR_VMID BIT(7) 76 #define TRCCONFIGR_TS BIT(11) 77 #define TRCCONFIGR_RS BIT(12) 78 #define TRCCONFIGR_VMIDOPT BIT(15) 79 80 /* ETMv3 ETMCR register bits */ 81 #define ETMCR_CYC_ACC BIT(12) 82 #define ETMCR_TIMESTAMP_EN BIT(28) 83 #define ETMCR_RETURN_STACK BIT(29) 84 85 static bool cs_etm_is_ete(struct perf_pmu *cs_etm_pmu, struct perf_cpu cpu); 86 static int cs_etm_get_ro(struct perf_pmu *pmu, struct perf_cpu cpu, const char *path, __u64 *val); 87 static bool cs_etm_pmu_path_exists(struct perf_pmu *pmu, struct perf_cpu cpu, const char *path); 88 89 static enum cs_etm_version cs_etm_get_version(struct perf_pmu *cs_etm_pmu, 90 struct perf_cpu cpu) 91 { 92 if (cs_etm_is_ete(cs_etm_pmu, cpu)) 93 return CS_ETE; 94 else if (cs_etm_pmu_path_exists(cs_etm_pmu, cpu, metadata_etmv4_ro[CS_ETMV4_TRCIDR0])) 95 return CS_ETMV4; 96 else if (cs_etm_pmu_path_exists(cs_etm_pmu, cpu, metadata_etmv3_ro[CS_ETM_ETMCCER])) 97 return CS_ETMV3; 98 99 return CS_NOT_PRESENT; 100 } 101 102 static int cs_etm_validate_context_id(struct perf_pmu *cs_etm_pmu, struct evsel *evsel, 103 struct perf_cpu cpu) 104 { 105 int err; 106 u64 ctxt, ctxt1, ctxt2; 107 __u64 trcidr2; 108 109 evsel__get_config_val(evsel, "contextid", &ctxt); 110 evsel__get_config_val(evsel, "contextid1", &ctxt1); 111 evsel__get_config_val(evsel, "contextid2", &ctxt2); 112 113 if (!ctxt && !ctxt1 && !ctxt2) 114 return 0; 115 116 /* Not supported in etmv3 */ 117 if (cs_etm_get_version(cs_etm_pmu, cpu) == CS_ETMV3) { 118 pr_err("%s: contextid not supported in ETMv3, disable with %s/contextid=0/\n", 119 CORESIGHT_ETM_PMU_NAME, CORESIGHT_ETM_PMU_NAME); 120 return -EINVAL; 121 } 122 123 /* Get a handle on TRCIDR2 */ 124 err = cs_etm_get_ro(cs_etm_pmu, cpu, metadata_etmv4_ro[CS_ETMV4_TRCIDR2], &trcidr2); 125 if (err) 126 return err; 127 128 if (ctxt1) { 129 /* 130 * TRCIDR2.CIDSIZE, bit [9-5], indicates whether contextID 131 * tracing is supported: 132 * 0b00000 Context ID tracing is not supported. 133 * 0b00100 Maximum of 32-bit Context ID size. 134 * All other values are reserved. 135 */ 136 if (BMVAL(trcidr2, 5, 9) != 0x4) { 137 pr_err("%s: CONTEXTIDR_EL1 isn't supported, disable with %s/contextid1=0/\n", 138 CORESIGHT_ETM_PMU_NAME, CORESIGHT_ETM_PMU_NAME); 139 return -EINVAL; 140 } 141 } 142 143 if (ctxt2) { 144 /* 145 * TRCIDR2.VMIDOPT[30:29] != 0 and 146 * TRCIDR2.VMIDSIZE[14:10] == 0b00100 (32bit virtual contextid) 147 * We can't support CONTEXTIDR in VMID if the size of the 148 * virtual context id is < 32bit. 149 * Any value of VMIDSIZE >= 4 (i.e, > 32bit) is fine for us. 150 */ 151 if (!BMVAL(trcidr2, 29, 30) || BMVAL(trcidr2, 10, 14) < 4) { 152 pr_err("%s: CONTEXTIDR_EL2 isn't supported, disable with %s/contextid2=0/\n", 153 CORESIGHT_ETM_PMU_NAME, CORESIGHT_ETM_PMU_NAME); 154 return -EINVAL; 155 } 156 } 157 158 return 0; 159 } 160 161 static int cs_etm_validate_timestamp(struct perf_pmu *cs_etm_pmu, struct evsel *evsel, 162 struct perf_cpu cpu) 163 { 164 int err; 165 u64 val; 166 __u64 trcidr0; 167 168 evsel__get_config_val(evsel, "timestamp", &val); 169 if (!val) 170 return 0; 171 172 if (cs_etm_get_version(cs_etm_pmu, cpu) == CS_ETMV3) { 173 pr_err("%s: timestamp not supported in ETMv3, disable with %s/timestamp=0/\n", 174 CORESIGHT_ETM_PMU_NAME, CORESIGHT_ETM_PMU_NAME); 175 return -EINVAL; 176 } 177 178 /* Get a handle on TRCIRD0 */ 179 err = cs_etm_get_ro(cs_etm_pmu, cpu, metadata_etmv4_ro[CS_ETMV4_TRCIDR0], &trcidr0); 180 if (err) 181 return err; 182 183 /* 184 * TRCIDR0.TSSIZE, bit [28-24], indicates whether global timestamping 185 * is supported: 186 * 0b00000 Global timestamping is not implemented 187 * 0b00110 Implementation supports a maximum timestamp of 48bits. 188 * 0b01000 Implementation supports a maximum timestamp of 64bits. 189 */ 190 trcidr0 &= GENMASK(28, 24); 191 if (!trcidr0) 192 return -EINVAL; 193 194 return 0; 195 } 196 197 static struct perf_pmu *cs_etm_get_pmu(struct auxtrace_record *itr) 198 { 199 struct cs_etm_recording *ptr = container_of(itr, struct cs_etm_recording, itr); 200 201 return ptr->cs_etm_pmu; 202 } 203 204 /* 205 * Check whether the requested timestamp and contextid options should be 206 * available on all requested CPUs and if not, tell the user how to override. 207 * The kernel will silently disable any unavailable options so a warning here 208 * first is better. In theory the kernel could still disable the option for 209 * some other reason so this is best effort only. 210 */ 211 static int cs_etm_validate_config(struct perf_pmu *cs_etm_pmu, 212 struct evsel *evsel) 213 { 214 int idx, err = 0; 215 struct perf_cpu_map *event_cpus = evsel->evlist->core.user_requested_cpus; 216 struct perf_cpu_map *intersect_cpus; 217 struct perf_cpu cpu; 218 219 /* 220 * Set option of each CPU we have. In per-cpu case, do the validation 221 * for CPUs to work with. In per-thread case, the CPU map has the "any" 222 * CPU value. Since the traced program can run on any CPUs in this case, 223 * thus don't skip validation. 224 */ 225 if (!perf_cpu_map__has_any_cpu(event_cpus)) { 226 struct perf_cpu_map *online_cpus = perf_cpu_map__new_online_cpus(); 227 228 intersect_cpus = perf_cpu_map__intersect(event_cpus, online_cpus); 229 perf_cpu_map__put(online_cpus); 230 } else { 231 intersect_cpus = perf_cpu_map__new_online_cpus(); 232 } 233 234 perf_cpu_map__for_each_cpu_skip_any(cpu, idx, intersect_cpus) { 235 if (cs_etm_get_version(cs_etm_pmu, cpu) == CS_NOT_PRESENT) { 236 pr_err("%s: Not found on CPU %d. Check hardware and firmware support and that all Coresight drivers are loaded\n", 237 CORESIGHT_ETM_PMU_NAME, cpu.cpu); 238 return -EINVAL; 239 } 240 err = cs_etm_validate_context_id(cs_etm_pmu, evsel, cpu); 241 if (err) 242 break; 243 244 err = cs_etm_validate_timestamp(cs_etm_pmu, evsel, cpu); 245 if (err) 246 break; 247 } 248 249 perf_cpu_map__put(intersect_cpus); 250 return err; 251 } 252 253 static int cs_etm_parse_snapshot_options(struct auxtrace_record *itr, 254 struct record_opts *opts, 255 const char *str) 256 { 257 struct cs_etm_recording *ptr = 258 container_of(itr, struct cs_etm_recording, itr); 259 unsigned long long snapshot_size = 0; 260 char *endptr; 261 262 if (str) { 263 snapshot_size = strtoull(str, &endptr, 0); 264 if (*endptr || snapshot_size > SIZE_MAX) 265 return -1; 266 } 267 268 opts->auxtrace_snapshot_mode = true; 269 opts->auxtrace_snapshot_size = snapshot_size; 270 ptr->snapshot_size = snapshot_size; 271 272 return 0; 273 } 274 275 /* 276 * If the sink name format "@sink_name" is used, lookup the sink by name to convert to 277 * "sinkid=sink_hash" format. If the user has already manually provided a hash then 278 * "sinkid" isn't overwritten. If neither are provided then the driver will pick the best 279 * sink. 280 */ 281 static int cs_etm_set_sink_attr(struct perf_pmu *pmu, 282 struct evsel *evsel) 283 { 284 char msg[BUFSIZ], path[PATH_MAX], *sink; 285 struct evsel_config_term *term; 286 u32 hash; 287 int ret; 288 289 list_for_each_entry(term, &evsel->config_terms, list) { 290 if (term->type != EVSEL__CONFIG_TERM_DRV_CFG) 291 continue; 292 293 sink = term->val.str; 294 snprintf(path, PATH_MAX, "sinks/%s", sink); 295 296 ret = perf_pmu__scan_file(pmu, path, "%x", &hash); 297 if (ret != 1) { 298 if (errno == ENOENT) 299 pr_err("Couldn't find sink \"%s\" on event %s\n" 300 "Missing kernel or device support?\n\n" 301 "Hint: An appropriate sink will be picked automatically if one isn't specified.\n", 302 sink, evsel__name(evsel)); 303 else 304 pr_err("Failed to set sink \"%s\" on event %s with %d (%s)\n", 305 sink, evsel__name(evsel), errno, 306 str_error_r(errno, msg, sizeof(msg))); 307 return ret; 308 } 309 310 evsel__set_config_if_unset(evsel, "sinkid", hash); 311 return 0; 312 } 313 314 return 0; 315 } 316 317 static struct evsel *cs_etm_get_evsel(struct evlist *evlist, 318 struct perf_pmu *cs_etm_pmu) 319 { 320 struct evsel *evsel; 321 322 evlist__for_each_entry(evlist, evsel) { 323 if (evsel->core.attr.type == cs_etm_pmu->type) 324 return evsel; 325 } 326 327 return NULL; 328 } 329 330 static int cs_etm_recording_options(struct auxtrace_record *itr, 331 struct evlist *evlist, 332 struct record_opts *opts) 333 { 334 int ret; 335 struct cs_etm_recording *ptr = 336 container_of(itr, struct cs_etm_recording, itr); 337 struct perf_pmu *cs_etm_pmu = ptr->cs_etm_pmu; 338 struct evsel *evsel, *cs_etm_evsel = NULL; 339 struct perf_cpu_map *cpus = evlist->core.user_requested_cpus; 340 bool privileged = perf_event_paranoid_check(-1); 341 int err = 0; 342 343 evlist__for_each_entry(evlist, evsel) { 344 if (evsel->core.attr.type == cs_etm_pmu->type) { 345 if (cs_etm_evsel) { 346 pr_err("There may be only one %s event\n", 347 CORESIGHT_ETM_PMU_NAME); 348 return -EINVAL; 349 } 350 cs_etm_evsel = evsel; 351 } 352 } 353 354 /* no need to continue if at least one event of interest was found */ 355 if (!cs_etm_evsel) 356 return 0; 357 358 ptr->evlist = evlist; 359 ptr->snapshot_mode = opts->auxtrace_snapshot_mode; 360 361 if (!record_opts__no_switch_events(opts) && 362 perf_can_record_switch_events()) 363 opts->record_switch_events = true; 364 365 cs_etm_evsel->needs_auxtrace_mmap = true; 366 opts->full_auxtrace = true; 367 368 ret = cs_etm_set_sink_attr(cs_etm_pmu, cs_etm_evsel); 369 if (ret) 370 return ret; 371 372 if (opts->use_clockid) { 373 pr_err("Cannot use clockid (-k option) with %s\n", 374 CORESIGHT_ETM_PMU_NAME); 375 return -EINVAL; 376 } 377 378 /* we are in snapshot mode */ 379 if (opts->auxtrace_snapshot_mode) { 380 /* 381 * No size were given to '-S' or '-m,', so go with 382 * the default 383 */ 384 if (!opts->auxtrace_snapshot_size && 385 !opts->auxtrace_mmap_pages) { 386 if (privileged) { 387 opts->auxtrace_mmap_pages = MiB(4) / page_size; 388 } else { 389 opts->auxtrace_mmap_pages = 390 KiB(128) / page_size; 391 if (opts->mmap_pages == UINT_MAX) 392 opts->mmap_pages = KiB(256) / page_size; 393 } 394 } else if (!opts->auxtrace_mmap_pages && !privileged && 395 opts->mmap_pages == UINT_MAX) { 396 opts->mmap_pages = KiB(256) / page_size; 397 } 398 399 /* 400 * '-m,xyz' was specified but no snapshot size, so make the 401 * snapshot size as big as the auxtrace mmap area. 402 */ 403 if (!opts->auxtrace_snapshot_size) { 404 opts->auxtrace_snapshot_size = 405 opts->auxtrace_mmap_pages * (size_t)page_size; 406 } 407 408 /* 409 * -Sxyz was specified but no auxtrace mmap area, so make the 410 * auxtrace mmap area big enough to fit the requested snapshot 411 * size. 412 */ 413 if (!opts->auxtrace_mmap_pages) { 414 size_t sz = opts->auxtrace_snapshot_size; 415 416 sz = round_up(sz, page_size) / page_size; 417 opts->auxtrace_mmap_pages = roundup_pow_of_two(sz); 418 } 419 420 /* Snapshot size can't be bigger than the auxtrace area */ 421 if (opts->auxtrace_snapshot_size > 422 opts->auxtrace_mmap_pages * (size_t)page_size) { 423 pr_err("Snapshot size %zu must not be greater than AUX area tracing mmap size %zu\n", 424 opts->auxtrace_snapshot_size, 425 opts->auxtrace_mmap_pages * (size_t)page_size); 426 return -EINVAL; 427 } 428 429 /* Something went wrong somewhere - this shouldn't happen */ 430 if (!opts->auxtrace_snapshot_size || 431 !opts->auxtrace_mmap_pages) { 432 pr_err("Failed to calculate default snapshot size and/or AUX area tracing mmap pages\n"); 433 return -EINVAL; 434 } 435 } 436 437 /* Buffer sizes weren't specified with '-m,xyz' so give some defaults */ 438 if (!opts->auxtrace_mmap_pages) { 439 if (privileged) { 440 opts->auxtrace_mmap_pages = MiB(4) / page_size; 441 } else { 442 opts->auxtrace_mmap_pages = KiB(128) / page_size; 443 if (opts->mmap_pages == UINT_MAX) 444 opts->mmap_pages = KiB(256) / page_size; 445 } 446 } 447 448 if (opts->auxtrace_snapshot_mode) 449 pr_debug2("%s snapshot size: %zu\n", CORESIGHT_ETM_PMU_NAME, 450 opts->auxtrace_snapshot_size); 451 452 /* 453 * To obtain the auxtrace buffer file descriptor, the auxtrace 454 * event must come first. 455 */ 456 evlist__to_front(evlist, cs_etm_evsel); 457 458 /* 459 * get the CPU on the sample - need it to associate trace ID in the 460 * AUX_OUTPUT_HW_ID event, and the AUX event for per-cpu mmaps. 461 */ 462 evsel__set_sample_bit(cs_etm_evsel, CPU); 463 464 /* 465 * Also the case of per-cpu mmaps, need the contextID in order to be notified 466 * when a context switch happened. 467 */ 468 if (!perf_cpu_map__is_any_cpu_or_is_empty(cpus)) { 469 evsel__set_config_if_unset(cs_etm_evsel, "timestamp", 1); 470 evsel__set_config_if_unset(cs_etm_evsel, "contextid", 1); 471 } 472 473 /* 474 * When the option '--timestamp' or '-T' is enabled, the PERF_SAMPLE_TIME 475 * bit is set for all events. In this case, always enable Arm CoreSight 476 * timestamp tracing. 477 */ 478 if (opts->sample_time_set) 479 evsel__set_config_if_unset(cs_etm_evsel, "timestamp", 1); 480 481 /* Add dummy event to keep tracking */ 482 err = parse_event(evlist, "dummy:u"); 483 if (err) 484 goto out; 485 evsel = evlist__last(evlist); 486 evlist__set_tracking_event(evlist, evsel); 487 evsel->core.attr.freq = 0; 488 evsel->core.attr.sample_period = 1; 489 490 /* In per-cpu case, always need the time of mmap events etc */ 491 if (!perf_cpu_map__is_any_cpu_or_is_empty(cpus)) 492 evsel__set_sample_bit(evsel, TIME); 493 494 err = cs_etm_validate_config(cs_etm_pmu, cs_etm_evsel); 495 out: 496 return err; 497 } 498 499 static u64 cs_etm_synth_etmcr(struct auxtrace_record *itr) 500 { 501 struct cs_etm_recording *ptr = 502 container_of(itr, struct cs_etm_recording, itr); 503 struct perf_pmu *cs_etm_pmu = ptr->cs_etm_pmu; 504 struct evsel *evsel = cs_etm_get_evsel(ptr->evlist, cs_etm_pmu); 505 u64 etmcr = 0; 506 u64 val; 507 508 if (!evsel) 509 return 0; 510 511 /* 512 * Synthesize what the kernel programmed into ETMCR based on 513 * what options the event was opened with. This doesn't have to be 514 * complete or 100% accurate, not all bits used by OpenCSD anyway. 515 */ 516 if (!evsel__get_config_val(evsel, "cycacc", &val) && val) 517 etmcr |= ETMCR_CYC_ACC; 518 if (!evsel__get_config_val(evsel, "timestamp", &val) && val) 519 etmcr |= ETMCR_TIMESTAMP_EN; 520 if (!evsel__get_config_val(evsel, "retstack", &val) && val) 521 etmcr |= ETMCR_RETURN_STACK; 522 523 return etmcr; 524 } 525 526 static u64 cs_etmv4_synth_trcconfigr(struct auxtrace_record *itr) 527 { 528 u64 trcconfigr = 0; 529 struct cs_etm_recording *ptr = 530 container_of(itr, struct cs_etm_recording, itr); 531 struct perf_pmu *cs_etm_pmu = ptr->cs_etm_pmu; 532 struct evsel *evsel = cs_etm_get_evsel(ptr->evlist, cs_etm_pmu); 533 u64 val; 534 535 if (!evsel) 536 return 0; 537 538 /* 539 * Synthesize what the kernel programmed into TRCCONFIGR based on 540 * what options the event was opened with. This doesn't have to be 541 * complete or 100% accurate, not all bits used by OpenCSD anyway. 542 */ 543 if (!evsel__get_config_val(evsel, "cycacc", &val) && val) 544 trcconfigr |= TRCCONFIGR_CCI; 545 if (!evsel__get_config_val(evsel, "contextid1", &val) && val) 546 trcconfigr |= TRCCONFIGR_CID; 547 if (!evsel__get_config_val(evsel, "timestamp", &val) && val) 548 trcconfigr |= TRCCONFIGR_TS; 549 if (!evsel__get_config_val(evsel, "retstack", &val) && val) 550 trcconfigr |= TRCCONFIGR_RS; 551 if (!evsel__get_config_val(evsel, "contextid2", &val) && val) 552 trcconfigr |= TRCCONFIGR_VMID | TRCCONFIGR_VMIDOPT; 553 if (!evsel__get_config_val(evsel, "branch_broadcast", &val) && val) 554 trcconfigr |= TRCCONFIGR_BB; 555 556 return trcconfigr; 557 } 558 559 static size_t 560 cs_etm_info_priv_size(struct auxtrace_record *itr, 561 struct evlist *evlist) 562 { 563 int idx; 564 int etmv3 = 0, etmv4 = 0, ete = 0; 565 struct perf_cpu_map *event_cpus = evlist->core.user_requested_cpus; 566 struct perf_cpu_map *intersect_cpus; 567 struct perf_cpu cpu; 568 struct perf_pmu *cs_etm_pmu = cs_etm_get_pmu(itr); 569 570 if (!perf_cpu_map__has_any_cpu(event_cpus)) { 571 /* cpu map is not "any" CPU , we have specific CPUs to work with */ 572 struct perf_cpu_map *online_cpus = perf_cpu_map__new_online_cpus(); 573 574 intersect_cpus = perf_cpu_map__intersect(event_cpus, online_cpus); 575 perf_cpu_map__put(online_cpus); 576 } else { 577 /* Event can be "any" CPU so count all online CPUs. */ 578 intersect_cpus = perf_cpu_map__new_online_cpus(); 579 } 580 /* Count number of each type of ETM. Don't count if that CPU has CS_NOT_PRESENT. */ 581 perf_cpu_map__for_each_cpu_skip_any(cpu, idx, intersect_cpus) { 582 enum cs_etm_version v = cs_etm_get_version(cs_etm_pmu, cpu); 583 584 ete += v == CS_ETE; 585 etmv4 += v == CS_ETMV4; 586 etmv3 += v == CS_ETMV3; 587 } 588 perf_cpu_map__put(intersect_cpus); 589 590 return (CS_ETM_HEADER_SIZE + 591 (ete * CS_ETE_PRIV_SIZE) + 592 (etmv4 * CS_ETMV4_PRIV_SIZE) + 593 (etmv3 * CS_ETMV3_PRIV_SIZE)); 594 } 595 596 static int cs_etm_get_ro(struct perf_pmu *pmu, struct perf_cpu cpu, const char *path, __u64 *val) 597 { 598 char pmu_path[PATH_MAX]; 599 int scan; 600 601 /* Get RO metadata from sysfs */ 602 snprintf(pmu_path, PATH_MAX, "cpu%d/%s", cpu.cpu, path); 603 604 scan = perf_pmu__scan_file(pmu, pmu_path, "%llx", val); 605 if (scan != 1) { 606 pr_err("%s: error reading: %s\n", __func__, pmu_path); 607 return -EINVAL; 608 } 609 610 return 0; 611 } 612 613 static int cs_etm_get_ro_signed(struct perf_pmu *pmu, struct perf_cpu cpu, const char *path, 614 __u64 *out_val) 615 { 616 char pmu_path[PATH_MAX]; 617 int scan; 618 int val = 0; 619 620 /* Get RO metadata from sysfs */ 621 snprintf(pmu_path, PATH_MAX, "cpu%d/%s", cpu.cpu, path); 622 623 scan = perf_pmu__scan_file(pmu, pmu_path, "%d", &val); 624 if (scan != 1) { 625 pr_err("%s: error reading: %s\n", __func__, pmu_path); 626 return -EINVAL; 627 } 628 629 *out_val = (__u64) val; 630 return 0; 631 } 632 633 static bool cs_etm_pmu_path_exists(struct perf_pmu *pmu, struct perf_cpu cpu, const char *path) 634 { 635 char pmu_path[PATH_MAX]; 636 637 /* Get RO metadata from sysfs */ 638 snprintf(pmu_path, PATH_MAX, "cpu%d/%s", cpu.cpu, path); 639 640 return perf_pmu__file_exists(pmu, pmu_path); 641 } 642 643 #define TRCDEVARCH_ARCHPART_SHIFT 0 644 #define TRCDEVARCH_ARCHPART_MASK GENMASK(11, 0) 645 #define TRCDEVARCH_ARCHPART(x) (((x) & TRCDEVARCH_ARCHPART_MASK) >> TRCDEVARCH_ARCHPART_SHIFT) 646 647 #define TRCDEVARCH_ARCHVER_SHIFT 12 648 #define TRCDEVARCH_ARCHVER_MASK GENMASK(15, 12) 649 #define TRCDEVARCH_ARCHVER(x) (((x) & TRCDEVARCH_ARCHVER_MASK) >> TRCDEVARCH_ARCHVER_SHIFT) 650 651 static bool cs_etm_is_ete(struct perf_pmu *cs_etm_pmu, struct perf_cpu cpu) 652 { 653 __u64 trcdevarch; 654 655 if (!cs_etm_pmu_path_exists(cs_etm_pmu, cpu, metadata_ete_ro[CS_ETE_TRCDEVARCH])) 656 return false; 657 658 cs_etm_get_ro(cs_etm_pmu, cpu, metadata_ete_ro[CS_ETE_TRCDEVARCH], &trcdevarch); 659 /* 660 * ETE if ARCHVER is 5 (ARCHVER is 4 for ETM) and ARCHPART is 0xA13. 661 * See ETM_DEVARCH_ETE_ARCH in coresight-etm4x.h 662 */ 663 return TRCDEVARCH_ARCHVER(trcdevarch) == 5 && TRCDEVARCH_ARCHPART(trcdevarch) == 0xA13; 664 } 665 666 static __u64 cs_etm_get_legacy_trace_id(struct perf_cpu cpu) 667 { 668 /* Wrap at 48 so that invalid trace IDs aren't saved into files. */ 669 return CORESIGHT_LEGACY_CPU_TRACE_ID(cpu.cpu % 48); 670 } 671 672 static void cs_etm_save_etmv4_header(__u64 data[], struct auxtrace_record *itr, struct perf_cpu cpu) 673 { 674 struct cs_etm_recording *ptr = container_of(itr, struct cs_etm_recording, itr); 675 struct perf_pmu *cs_etm_pmu = ptr->cs_etm_pmu; 676 677 /* Get trace configuration register */ 678 data[CS_ETMV4_TRCCONFIGR] = cs_etmv4_synth_trcconfigr(itr); 679 /* traceID set to legacy version, in case new perf running on older system */ 680 data[CS_ETMV4_TRCTRACEIDR] = cs_etm_get_legacy_trace_id(cpu); 681 682 /* Get read-only information from sysFS */ 683 cs_etm_get_ro(cs_etm_pmu, cpu, metadata_etmv4_ro[CS_ETMV4_TRCIDR0], 684 &data[CS_ETMV4_TRCIDR0]); 685 cs_etm_get_ro(cs_etm_pmu, cpu, metadata_etmv4_ro[CS_ETMV4_TRCIDR1], 686 &data[CS_ETMV4_TRCIDR1]); 687 cs_etm_get_ro(cs_etm_pmu, cpu, metadata_etmv4_ro[CS_ETMV4_TRCIDR2], 688 &data[CS_ETMV4_TRCIDR2]); 689 cs_etm_get_ro(cs_etm_pmu, cpu, metadata_etmv4_ro[CS_ETMV4_TRCIDR8], 690 &data[CS_ETMV4_TRCIDR8]); 691 cs_etm_get_ro(cs_etm_pmu, cpu, metadata_etmv4_ro[CS_ETMV4_TRCAUTHSTATUS], 692 &data[CS_ETMV4_TRCAUTHSTATUS]); 693 694 /* Kernels older than 5.19 may not expose ts_source */ 695 if (!cs_etm_pmu_path_exists(cs_etm_pmu, cpu, metadata_etmv4_ro[CS_ETMV4_TS_SOURCE]) || 696 cs_etm_get_ro_signed(cs_etm_pmu, cpu, metadata_etmv4_ro[CS_ETMV4_TS_SOURCE], 697 &data[CS_ETMV4_TS_SOURCE])) { 698 pr_debug3("[%03d] pmu file 'ts_source' not found. Fallback to safe value (-1)\n", 699 cpu.cpu); 700 data[CS_ETMV4_TS_SOURCE] = (__u64) -1; 701 } 702 } 703 704 static void cs_etm_save_ete_header(__u64 data[], struct auxtrace_record *itr, struct perf_cpu cpu) 705 { 706 struct cs_etm_recording *ptr = container_of(itr, struct cs_etm_recording, itr); 707 struct perf_pmu *cs_etm_pmu = ptr->cs_etm_pmu; 708 709 /* Get trace configuration register */ 710 data[CS_ETE_TRCCONFIGR] = cs_etmv4_synth_trcconfigr(itr); 711 /* traceID set to legacy version, in case new perf running on older system */ 712 data[CS_ETE_TRCTRACEIDR] = cs_etm_get_legacy_trace_id(cpu); 713 714 /* Get read-only information from sysFS */ 715 cs_etm_get_ro(cs_etm_pmu, cpu, metadata_ete_ro[CS_ETE_TRCIDR0], &data[CS_ETE_TRCIDR0]); 716 cs_etm_get_ro(cs_etm_pmu, cpu, metadata_ete_ro[CS_ETE_TRCIDR1], &data[CS_ETE_TRCIDR1]); 717 cs_etm_get_ro(cs_etm_pmu, cpu, metadata_ete_ro[CS_ETE_TRCIDR2], &data[CS_ETE_TRCIDR2]); 718 cs_etm_get_ro(cs_etm_pmu, cpu, metadata_ete_ro[CS_ETE_TRCIDR8], &data[CS_ETE_TRCIDR8]); 719 cs_etm_get_ro(cs_etm_pmu, cpu, metadata_ete_ro[CS_ETE_TRCAUTHSTATUS], 720 &data[CS_ETE_TRCAUTHSTATUS]); 721 /* ETE uses the same registers as ETMv4 plus TRCDEVARCH */ 722 cs_etm_get_ro(cs_etm_pmu, cpu, metadata_ete_ro[CS_ETE_TRCDEVARCH], 723 &data[CS_ETE_TRCDEVARCH]); 724 725 /* Kernels older than 5.19 may not expose ts_source */ 726 if (!cs_etm_pmu_path_exists(cs_etm_pmu, cpu, metadata_ete_ro[CS_ETE_TS_SOURCE]) || 727 cs_etm_get_ro_signed(cs_etm_pmu, cpu, metadata_ete_ro[CS_ETE_TS_SOURCE], 728 &data[CS_ETE_TS_SOURCE])) { 729 pr_debug3("[%03d] pmu file 'ts_source' not found. Fallback to safe value (-1)\n", 730 cpu.cpu); 731 data[CS_ETE_TS_SOURCE] = (__u64) -1; 732 } 733 } 734 735 static void cs_etm_get_metadata(struct perf_cpu cpu, u32 *offset, 736 struct auxtrace_record *itr, 737 struct perf_record_auxtrace_info *info) 738 { 739 u32 increment, nr_trc_params; 740 u64 magic; 741 struct perf_pmu *cs_etm_pmu = cs_etm_get_pmu(itr); 742 743 /* first see what kind of tracer this cpu is affined to */ 744 switch (cs_etm_get_version(cs_etm_pmu, cpu)) { 745 case CS_ETE: 746 magic = __perf_cs_ete_magic; 747 cs_etm_save_ete_header(&info->priv[*offset], itr, cpu); 748 749 /* How much space was used */ 750 increment = CS_ETE_PRIV_MAX; 751 nr_trc_params = CS_ETE_PRIV_MAX - CS_ETM_COMMON_BLK_MAX_V1; 752 break; 753 754 case CS_ETMV4: 755 magic = __perf_cs_etmv4_magic; 756 cs_etm_save_etmv4_header(&info->priv[*offset], itr, cpu); 757 758 /* How much space was used */ 759 increment = CS_ETMV4_PRIV_MAX; 760 nr_trc_params = CS_ETMV4_PRIV_MAX - CS_ETMV4_TRCCONFIGR; 761 break; 762 763 case CS_ETMV3: 764 magic = __perf_cs_etmv3_magic; 765 /* Get configuration register */ 766 info->priv[*offset + CS_ETM_ETMCR] = cs_etm_synth_etmcr(itr); 767 /* traceID set to legacy value in case new perf running on old system */ 768 info->priv[*offset + CS_ETM_ETMTRACEIDR] = cs_etm_get_legacy_trace_id(cpu); 769 /* Get read-only information from sysFS */ 770 cs_etm_get_ro(cs_etm_pmu, cpu, metadata_etmv3_ro[CS_ETM_ETMCCER], 771 &info->priv[*offset + CS_ETM_ETMCCER]); 772 cs_etm_get_ro(cs_etm_pmu, cpu, metadata_etmv3_ro[CS_ETM_ETMIDR], 773 &info->priv[*offset + CS_ETM_ETMIDR]); 774 775 /* How much space was used */ 776 increment = CS_ETM_PRIV_MAX; 777 nr_trc_params = CS_ETM_PRIV_MAX - CS_ETM_ETMCR; 778 break; 779 780 default: 781 case CS_NOT_PRESENT: 782 /* Unreachable, CPUs already validated in cs_etm_validate_config() */ 783 assert(true); 784 return; 785 } 786 787 /* Build generic header portion */ 788 info->priv[*offset + CS_ETM_MAGIC] = magic; 789 info->priv[*offset + CS_ETM_CPU] = cpu.cpu; 790 info->priv[*offset + CS_ETM_NR_TRC_PARAMS] = nr_trc_params; 791 /* Where the next CPU entry should start from */ 792 *offset += increment; 793 } 794 795 static int cs_etm_info_fill(struct auxtrace_record *itr, 796 struct perf_session *session, 797 struct perf_record_auxtrace_info *info, 798 size_t priv_size) 799 { 800 int i; 801 u32 offset; 802 u64 nr_cpu, type; 803 struct perf_cpu_map *cpu_map; 804 struct perf_cpu_map *event_cpus = session->evlist->core.user_requested_cpus; 805 struct perf_cpu_map *online_cpus = perf_cpu_map__new_online_cpus(); 806 struct cs_etm_recording *ptr = 807 container_of(itr, struct cs_etm_recording, itr); 808 struct perf_pmu *cs_etm_pmu = ptr->cs_etm_pmu; 809 struct perf_cpu cpu; 810 811 if (priv_size != cs_etm_info_priv_size(itr, session->evlist)) 812 return -EINVAL; 813 814 if (!session->evlist->core.nr_mmaps) 815 return -EINVAL; 816 817 /* If the cpu_map has the "any" CPU all online CPUs are involved */ 818 if (perf_cpu_map__has_any_cpu(event_cpus)) { 819 cpu_map = online_cpus; 820 } else { 821 /* Make sure all specified CPUs are online */ 822 perf_cpu_map__for_each_cpu(cpu, i, event_cpus) { 823 if (!perf_cpu_map__has(online_cpus, cpu)) 824 return -EINVAL; 825 } 826 827 cpu_map = event_cpus; 828 } 829 830 nr_cpu = perf_cpu_map__nr(cpu_map); 831 /* Get PMU type as dynamically assigned by the core */ 832 type = cs_etm_pmu->type; 833 834 /* First fill out the session header */ 835 info->type = PERF_AUXTRACE_CS_ETM; 836 info->priv[CS_HEADER_VERSION] = CS_HEADER_CURRENT_VERSION; 837 info->priv[CS_PMU_TYPE_CPUS] = type << 32; 838 info->priv[CS_PMU_TYPE_CPUS] |= nr_cpu; 839 info->priv[CS_ETM_SNAPSHOT] = ptr->snapshot_mode; 840 841 offset = CS_ETM_SNAPSHOT + 1; 842 843 perf_cpu_map__for_each_cpu(cpu, i, cpu_map) { 844 assert(offset < priv_size); 845 cs_etm_get_metadata(cpu, &offset, itr, info); 846 } 847 848 perf_cpu_map__put(online_cpus); 849 850 return 0; 851 } 852 853 static int cs_etm_snapshot_start(struct auxtrace_record *itr) 854 { 855 struct cs_etm_recording *ptr = 856 container_of(itr, struct cs_etm_recording, itr); 857 struct evsel *evsel = cs_etm_get_evsel(ptr->evlist, ptr->cs_etm_pmu); 858 859 if (evsel) 860 return evsel__disable(evsel); 861 862 return -EINVAL; 863 } 864 865 static int cs_etm_snapshot_finish(struct auxtrace_record *itr) 866 { 867 struct cs_etm_recording *ptr = 868 container_of(itr, struct cs_etm_recording, itr); 869 struct evsel *evsel; 870 871 evlist__for_each_entry(ptr->evlist, evsel) { 872 if (evsel->core.attr.type == ptr->cs_etm_pmu->type) 873 return evsel__enable(evsel); 874 } 875 return -EINVAL; 876 } 877 878 static u64 cs_etm_reference(struct auxtrace_record *itr __maybe_unused) 879 { 880 return (((u64) rand() << 0) & 0x00000000FFFFFFFFull) | 881 (((u64) rand() << 32) & 0xFFFFFFFF00000000ull); 882 } 883 884 static void cs_etm_recording_free(struct auxtrace_record *itr) 885 { 886 struct cs_etm_recording *ptr = 887 container_of(itr, struct cs_etm_recording, itr); 888 889 free(ptr); 890 } 891 892 struct auxtrace_record *cs_etm_record_init(int *err) 893 { 894 struct perf_pmu *cs_etm_pmu; 895 struct cs_etm_recording *ptr; 896 897 cs_etm_pmu = perf_pmus__find(CORESIGHT_ETM_PMU_NAME); 898 899 if (!cs_etm_pmu) { 900 *err = -EINVAL; 901 goto out; 902 } 903 904 ptr = zalloc(sizeof(struct cs_etm_recording)); 905 if (!ptr) { 906 *err = -ENOMEM; 907 goto out; 908 } 909 910 ptr->cs_etm_pmu = cs_etm_pmu; 911 ptr->itr.parse_snapshot_options = cs_etm_parse_snapshot_options; 912 ptr->itr.recording_options = cs_etm_recording_options; 913 ptr->itr.info_priv_size = cs_etm_info_priv_size; 914 ptr->itr.info_fill = cs_etm_info_fill; 915 ptr->itr.snapshot_start = cs_etm_snapshot_start; 916 ptr->itr.snapshot_finish = cs_etm_snapshot_finish; 917 ptr->itr.reference = cs_etm_reference; 918 ptr->itr.free = cs_etm_recording_free; 919 ptr->itr.read_finish = auxtrace_record__read_finish; 920 921 *err = 0; 922 return &ptr->itr; 923 out: 924 return NULL; 925 } 926 927 /* 928 * Set a default config to enable the user changed config tracking mechanism 929 * (CFG_CHG and evsel__set_config_if_unset()). If no default is set then user 930 * changes aren't tracked. 931 */ 932 void 933 cs_etm_get_default_config(const struct perf_pmu *pmu __maybe_unused, 934 struct perf_event_attr *attr) 935 { 936 attr->sample_period = 1; 937 } 938