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