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