1# Collect ETM data for AutoFDO 2 3[TOC] 4 5## Introduction 6 7The ARM Embedded Trace Macrocell (ETM) is an instruction tracing unit available on ARM SoCs. ETM 8traces the instruction stream executed on each core and sends the stream to system memory via other 9Coresight components. ETM data contains branch records, similar to Last Branch Records (LBRs) on 10x86 architectures. 11 12Simpleperf supports collecting ETM data and converting it to input files for AutoFDO, which can 13then be used for Profile-Guided Optimization (PGO) during compilation. 14 15On ARMv8, the ETM and other Coresight components are considered part of the external debug 16interface. Therefore, they are typically only used internally and are disabled on production 17devices. ARMv9 introduces the Embedded Trace Extension (ETE) and Trace Buffer Extension (TRBE) 18to enhance self-hosted ETM data collection. This new hardware is not bound to the external debug 19interface and can be used more widely to collect AutoFDO profiles. 20 21For Pixel devices, ETM data collection is supported on EVT and DVT devices starting with Pixel 4. 22For other devices, you can try the commands in this document to see if ETM data recording is 23possible. To enable ETM data collection on a device, refer to the documentation in 24[Enable ETM data collection](#enable-etm-data-collection). 25 26## Examples 27 28Below are examples collecting ETM data for AutoFDO. It has two steps: first recording ETM data, 29second converting ETM data to AutoFDO input files. 30 31Record ETM data: 32 33```sh 34# preparation: we need to be root to record ETM data 35$ adb root 36$ adb shell 37redfin:/ \# cd data/local/tmp 38redfin:/data/local/tmp \# 39 40# Do a system wide collection, it writes output to perf.data. 41# If only want ETM data for kernel, use `-e cs-etm:k`. 42# If only want ETM data for userspace, use `-e cs-etm:u`. 43redfin:/data/local/tmp \# simpleperf record -e cs-etm --duration 3 -a 44 45# To reduce file size and time converting to AutoFDO input files, we recommend converting ETM data 46# into an intermediate branch-list format. 47redfin:/data/local/tmp \# simpleperf inject --output branch-list -o branch_list.data 48``` 49 50Converting ETM data to AutoFDO input files needs to read binaries. 51So for userspace libraries, they can be converted on device. For kernel, it needs 52to be converted on host, with vmlinux and kernel modules available. 53 54Convert ETM data for userspace libraries: 55 56```sh 57# Injecting ETM data on device. It writes output to perf_inject.data. 58# perf_inject.data is a text file, containing branch counts for each library. 59redfin:/data/local/tmp \# simpleperf inject -i branch_list.data 60``` 61 62Convert ETM data for kernel: 63 64```sh 65# pull ETM data to host. 66host $ adb pull /data/local/tmp/branch_list.data 67# download vmlinux and kernel modules to <binary_dir> 68# host simpleperf is in <aosp-top>/system/extras/simpleperf/scripts/bin/linux/x86_64/simpleperf, 69# or you can build simpleperf by `mmma system/extras/simpleperf`. 70host $ simpleperf inject --symdir <binary_dir> -i branch_list.data 71``` 72 73The generated perf_inject.data may contain branch info for multiple binaries. But AutoFDO only 74accepts one at a time. So we need to split perf_inject.data. 75The format of perf_inject.data is below: 76 77```perf_inject.data format 78 79executed range with count info for binary1 80branch with count info for binary1 81// name for binary1 82 83executed range with count info for binary2 84branch with count info for binary2 85// name for binary2 86 87... 88``` 89 90We need to split perf_inject.data, and make sure one file only contains info for one binary. 91 92Then we can use [AutoFDO](https://github.com/google/autofdo) to create profile. Follow README.md 93in AutoFDO to build create_llvm_prof, then use `create_llvm_prof` to create profiles for clang. 94 95```sh 96# perf_inject_binary1.data is split from perf_inject.data, and only contains branch info for binary1. 97host $ create_llvm_prof -profile perf_inject_binary1.data -profiler text -binary path_of_binary1 -out a.prof -format binary 98 99# perf_inject_kernel.data is split from perf_inject.data, and only contains branch info for [kernel.kallsyms]. 100host $ create_llvm_prof -profile perf_inject_kernel.data -profiler text -binary vmlinux -out a.prof -format binary 101``` 102 103Then we can use a.prof for PGO during compilation, via `-fprofile-sample-use=a.prof`. 104[Here](https://clang.llvm.org/docs/UsersManual.html#using-sampling-profilers) are more details. 105 106### A complete example: etm_test_loop.cpp 107 108`etm_test_loop.cpp` is an example to show the complete process. 109The source code is in [etm_test_loop.cpp](https://android.googlesource.com/platform/system/extras/+/main/simpleperf/runtest/etm_test_loop.cpp). 110The build script is in [Android.bp](https://android.googlesource.com/platform/system/extras/+/main/simpleperf/runtest/Android.bp). 111It builds an executable called `etm_test_loop`, which runs on device. 112 113**Step 1: Build `etm_test_loop` binary** 114 115```sh 116(host) <AOSP>$ . build/envsetup.sh 117(host) <AOSP>$ lunch aosp_arm64-trunk_staging-userdebug 118(host) <AOSP>$ make etm_test_loop 119``` 120 121**Step 2: Run `etm_test_loop` on device, and collect ETM data for its running** 122 123```sh 124(host) <AOSP>$ adb push out/target/product/generic_arm64/system/bin/etm_test_loop /data/local/tmp 125(host) <AOSP>$ adb root 126(host) <AOSP>$ adb shell 127(device) / $ cd /data/local/tmp 128(device) /data/local/tmp $ chmod a+x etm_test_loop 129(device) /data/local/tmp $ simpleperf record -e cs-etm:u ./etm_test_loop 130simpleperf I cmd_record.cpp:809] Recorded for 0.033556 seconds. Start post processing. 131simpleperf I cmd_record.cpp:879] Aux data traced: 1,134,720 132(device) /data/local/tmp $ simpleperf inject -i perf.data --output branch-list -o branch_list.data 133(device) /data/local/tmp $ exit 134(host) <AOSP>$ adb pull /data/local/tmp/branch_list.data 135``` 136 137**Step 3: Convert ETM data to AutoFDO profile** 138 139```sh 140# Build simpleperf tool on host. 141(host) <AOSP>$ make simpleperf_ndk 142(host) <AOSP>$ simpleperf inject -i branch_list.data -o perf_inject_etm_test_loop.data --symdir out/target/product/generic_arm64/symbols/system/bin 143(host) <AOSP>$ cat perf_inject_etm_test_loop.data 14414 1454000-4010:1 1464014-4048:1 147... 148418c->0:1 149// build_id: 0xa6fc5b506adf9884cdb680b4893c505a00000000 150// /data/local/tmp/etm_test_loop 151 152(host) <AOSP>$ create_llvm_prof -profile perf_inject_etm_test_loop.data -profiler text -binary out/target/product/generic_arm64/symbols/system/bin/etm_test_loop -out etm_test_loop.afdo -format binary 153(host) <AOSP>$ ls -lh etm_test_loop.afdo 154rw-r--r-- 1 user group 241 Apr 30 09:52 etm_test_loop.afdo 155``` 156 157**Step 4: Use AutoFDO profile to build optimized binary** 158 159```sh 160(host) <AOSP>$ cp etm_test_loop.afdo toolchain/pgo-profiles/sampling/ 161(host) <AOSP>$ vi toolchain/pgo-profiles/sampling/Android.bp 162# Edit Android.bp to add a fdo_profile module: 163# 164# fdo_profile { 165# name: "etm_test_loop", 166# profile: "etm_test_loop.afdo" 167# } 168(host) <AOSP>$ vi toolchain/pgo-profiles/sampling/afdo_profiles.mk 169# Edit afdo_profiles.mk to add etm_test_loop profile mapping: 170# 171# AFDO_PROFILES += keystore2://toolchain/pgo-profiles/sampling:keystore2 \ 172# ... 173# server_configurable_flags://toolchain/pgo-profiles/sampling:server_configurable_flags \ 174# etm_test_loop://toolchain/pgo-profiles/sampling:etm_test_loop 175# 176(host) <AOSP>$ vi system/extras/simpleperf/runtest/Android.bp 177# Edit Android.bp to enable afdo for etm_test_loop: 178# 179# cc_binary { 180# name: "etm_test_loop", 181# srcs: ["etm_test_loop.cpp"], 182# afdo: true, 183# } 184(host) <AOSP>$ make etm_test_loop 185``` 186 187We can check if `etm_test_loop.afdo` is used when building etm_test_loop. 188 189```sh 190(host) <AOSP>$ gzip -d out/verbose.log.gz 191(host) <AOSP>$ cat out/verbose.log | grep etm_test_loop.afdo 192 ... -fprofile-sample-use=toolchain/pgo-profiles/sampling/etm_test_loop.afdo ... 193``` 194 195If comparing the disassembly of `out/target/product/generic_arm64/symbols/system/bin/etm_test_loop` 196before and after optimizing with AutoFDO data, we can see different preferences when branching. 197 198### A complete example: kernel 199 200This example demonstrates how to collect ETM data for the Android kernel on a device, convert it to 201an AutoFDO profile on the host machine, and then use that profile to build an optimized kernel. 202 203 204**Step 1 (Optional): Build a Kernel with `-fdebug-info-for-profiling`** 205 206While not strictly required, we recommend building the vmlinux file with the 207`-fdebug-info-for-profiling` compiler flag. This option adds extra debug information that helps map 208instructions accurately to source code, improving profile quality. For more details, see 209[this LLVM review](https://reviews.llvm.org/D25435). 210 211An example of how to add this flag to a kernel build can be found in 212[this Android kernel commit](https://android-review.googlesource.com/c/kernel/common/+/3101987). 213 214 215**Step 2: Collect ETM data for the kernel on device** 216 217```sh 218(host) $ adb root && adb shell 219(device) / $ cd /data/local/tmp 220# Record ETM data while running a representative workload (e.g., launching applications or 221# running benchmarks): 222(device) / $ simpleperf record -e cs-etm:k -a --duration 60 -z -o perf.data 223simpleperf I cmd_record.cpp:826] Recorded for 60.0796 seconds. Start post processing. 224simpleperf I cmd_record.cpp:902] Aux data traced: 91,780,432 225simpleperf I cmd_record.cpp:894] Record compressed: 27.76 MB (original 110.13 MB, ratio 4) 226# Convert the raw ETM data to a branch list to reduce file size: 227(device) / $ mkdir branch_data 228(device) / $ simpleperf inject -i perf.data -o branch_data/branch01.data --output branch-list \ 229 --binary kernel.kallsyms 230(device) / $ ls branch01.data 231-rw-rw-rw- 1 root root 437K 2024-10-17 23:03 branch01.data 232# Run the record command and the inject command multiple times to capture a wider range of kernel 233# code execution. ETM data traces the instruction stream, and under heavy load, much of this data 234# can be lost due to overflow and rate limiting within simpleperf. Recording multiple profiles and 235# merging them improves coverage. 236``` 237 238Alternative: Instead of manual recording, you can use `profcollectd` to continuously collect ETM 239data in the background. See the [Collect ETM Data with a Daemon](#collect-etm-data-with-a-daemon) 240section for more information. 241 242 243**Step 3: Convert ETM data to AutoFDO Profile on Host** 244 245```sh 246(host) $ adb pull /data/local/tmp/branch_data 247(host) $ cd branch_data 248# Download the corresponding vmlinux file and place it in the current directory. 249# Merge the branch data files and generate an AutoFDO profile: 250(host) $ simpleperf inject -i branch01.data,branch02.data,... --binary kernel.kallsyms --symdir . \ 251 --allow-mismatched-build-id -o kernel.autofdo -j 20 252(host) $ ls -lh kernel.autofdo 253-rw-r--r-- 1 yabinc primarygroup 1.3M Oct 17 16:39 kernel.autofdo 254# Convert the AutoFDO profile to the LLVM profile format: 255(host) $ create_llvm_prof --profiler text --binary=vmlinux --profile=kernel.autofdo \ 256 --out=kernel.llvm_profdata --format extbinary 257(host) $ ls -lh kernel.llvm_profdata 258-rw-r--r-- 1 yabinc primarygroup 1.4M Oct 17 19:00 kernel.llvm_profdata 259``` 260 261**Step 4: Use the AutoFDO Profile when Building a New Kernel** 262 263Integrate the generated kernel.llvm_profdata file into your kernel build process. An example of 264how to use this profile data with vmlinux can be found in 265[this Android kernel commit](https://android-review.googlesource.com/c/kernel/common/+/3293642). 266 267 268## Convert ETM data for llvm-bolt (experiment) 269 270We can also convert ETM data to profiles for [llvm-bolt](https://github.com/llvm/llvm-project/tree/main/bolt). 271The binaries should have an unstripped symbol table, and linked with relocations (--emit-relocs or 272-q linker flag). 273 274```sh 275# symdir is the directory containting etm_test_loop with unstripped symbol table and relocations. 276(host) $ simpleperf inject -i perf.data --output bolt -o perf_inject_bolt.data --symdir symdir 277# Remove the comment line. 278(host) $ sed -i '/^\/\//d' perf_inject_bolt.data 279(host) $ <LLVM_BIN>/perf2bolt --pa -p=perf_inject_bolt.data -o perf.fdata symdir/etm_test_loop 280# --no-huge-pages and --align-text=0x4000 are used to avoid generating big binaries due to 281# alignment. See https://github.com/facebookarchive/BOLT/issues/138. 282# However, if the original binary is built with huge page alignments (-z max-page-size=0x200000), 283# then don't use these flags. 284(host) $ <LLVM_BIN>/llvm-bolt symdir/etm_test_loop -o etm_test_loop.bolt -data=perf.fdata \ 285 -reorder-blocks=ext-tsp -reorder-functions=hfsort -split-functions -split-all-cold \ 286 -split-eh -dyno-stats --no-huge-pages --align-text=0x4000 287``` 288 289## Collect ETM data with a daemon 290 291Android also has a daemon collecting ETM data periodically. It only runs on userdebug and eng 292devices. The source code is in https://android.googlesource.com/platform/system/extras/+/main/profcollectd/. 293 294## Options for collecting ETM data 295 296Simpleperf provides several options for ETM data collection, which are listed in the 297"ETM recording options" section of the `simpleperf record -h` output. Here's an introduction to some 298of them: 299 300ETM traces the instruction stream and can generate a large amount of data in a short time. The 301kernel uses a buffer to store this data. The default buffer size is 4MB, which can be controlled 302with the `--aux-buffer-size` option. Simpleperf periodically reads data from this buffer, by default 303every 100ms. This interval can be adjusted using the `--etm-flush-interval` option. If the buffer 304overflows, excess ETM data is lost. The default data generation rate is 40MB/s. This is true when 305using ETR, TRBE might copy data more frequently. 306 307To reduce storage size, ETM data can be compressed before being written to disk using the `-z` 308option. In practice, this reduces storage size by 75%. 309 310Another way to reduce storage size is to decode ETM data before storing it, using the `--decode-etm` 311option. This can achieve around a 98% reduction in storage size. However, it doubles CPU cycles and 312and power for recording, and can lead to data loss if processing doesn't keep up with the data 313generation rate. For this reason, profcollectd currently uses `-z` for compression instead of 314`--decode-etm`. 315 316## Enable ETM data collection 317 318To enable ETM data collection on a device, you must first verify that the required hardware is 319present. Then, you need to enable ETM in both the bootloader and the kernel. 320 321### Check hardware support 322 323In ARMv8, instruction tracing relies on two Coresight components: 324 325**Coresight ETM**: Generates the ETM data, recording the instruction stream. 326 327**Coresight ETR**: Transfers the ETM data to system memory for analysis. 328 329ARMv9 offers more flexibility with the introduction of new components: 330 331**Embedded Trace Extension (ETE)**: Replaces the Coresight ETM as the instruction trace source. 332 333**Trace Buffer Extension (TRBE)**: Provides an alternative to Coresight ETR for transferring trace 334data to memory. For example: 335 336Pixel 7: Uses Coresight ETM and Coresight ETR (ARMv8). 337 338Pixel 8: Uses ETE and Coresight ETR (ARMv9). While the Pixel 8 has TRBE, known errata with TRBE on 339 its Cortex cores makes it unsuitable for use. 340 341Finding Device Support Information: 342 343**ETE and TRBE support**: Refer to the relevant core's technical reference manual (e.g., 344 [Arm® Cortex-X4 Core Technical Reference Manual](https://developer.arm.com/documentation/102484/0002)). 345 346**TRBE errata**: Consult the core's errata notice (e.g., 347 [Arm® Cortex-X4 (MP161) Software Developer Errata Notice](https://developer.arm.com/documentation/SDEN-2432808/0800/?lang=en)). 348 349**Coresight ETR support**: Typically detailed in the SoC's manual. 350 351### Enable ETM in the bootloader 352 353To enable Coresight ETM and Coresight ETR on ARMv8 devices (or only Coresight ETR on ARMv9 devices), 354you need to allow non-secure, non-invasive debug access on the CPU. The specific method for doing 355this varies depending on the SoC. After enabling ETM in the bootloader and kernel, you can verify 356that Coresight ETM and ETR are operational by checking their respective `TRCAUTHSTATUS` registers. 357Following is an example of Pixel 6 with ETM enabled: 358 359```sh 360oriole:/ # cat /sys/bus/coresight/devices/etm0/mgmt/trcauthstatus 3610xcc 362oriole:/ # cat /sys/bus/coresight/devices/tmc_etr0/mgmt/authstatus 3630x33 364``` 365 366To enable ETE on ARMv9 devices, you need to allow the kernel to access trace system registers. This 367is done by setting the `ENABLE_SYS_REG_TRACE_FOR_NS` build option in Trusted Firmware-A (see 368[documentation](https://trustedfirmware-a.readthedocs.io/en/v2.11/getting_started/build-options.html)). 369 370To enable TRBE on ARMv9 devices, you need to allow the kernel to access trace buffer control 371registers. This is done by setting the `ENABLE_TRBE_FOR_NS` build option in Trusted Firmware-A (see 372[documentation](https://trustedfirmware-a.readthedocs.io/en/v2.11/getting_started/build-options.html)). 373 374 375### Enable ETM in the kernel 376 377Android kernels from version 6.x onwards generally include the necessary patches for ETM data 378collection. To enable ETM in the kernel, you need to build the required kernel modules and add the 379appropriate device tree entries. 380 381Enable the following kernel configuration options to include the ETM kernel modules: 382```config 383 CONFIG_CORESIGHT=m 384 CONFIG_CORESIGHT_LINK_AND_SINK_TMC=m 385 CONFIG_CORESIGHT_SOURCE_ETM4X=m 386 CONFIG_CORESIGHT_TRBE=m 387``` 388 389These options will build the following kernel modules: 390``` 391coresight.ko 392coresight-etm4x.ko 393coresight-funnel.ko 394coresight-replicator.ko 395coresight-tmc.ko 396coresight-trbe.ko 397``` 398 399Different SoCs have varying Coresight device connections, address assignments, and interrupt 400configurations. Therefore, providing a universal device tree example is not feasible. However, the 401following examples from Pixel devices illustrate how device tree entries for ETM components might 402look. 403 404**Example 1: Coresight ETM and Coresight ETR (Pixel 6)** 405 406This example shows the device tree entries for Coresight ETM and ETR on Pixel 6 407(source: [gs101-debug.dtsi](https://android.googlesource.com/kernel/devices/google/gs101/+/refs/heads/android-gs-tangorpro-6.1-android16-dp/dts/gs101-debug.dtsi#287)). 408 409```device-tree 410etm0: etm@25840000 { 411 compatible = "arm,primecell"; 412 arm,primecell-periphid = <0x000bb95d>; 413 reg = <0 0x25840000 0x1000>; 414 cpu = <&cpu0>; 415 coresight-name = "coresight-etm0"; 416 clocks = <&clock ATCLK>; 417 clock-names = "apb_pclk"; 418 arm,coresight-loses-context-with-cpu; 419 out-ports { 420 port { 421 etm0_out_port: endpoint { 422 remote-endpoint = <&funnel0_in_port0>; 423 }; 424 }; 425 }; 426}; 427 428// ... etm1 to etm7, funnel0 to funnel2, etf0, etf1 ... 429 430etr: etr@2500a000 { 431 compatible = "arm,coresight-tmc", "arm,primecell"; 432 arm,primecell-periphid = <0x001bb961>; 433 reg = <0 0x2500a000 0x1000>; 434 coresight-name = "coresight-etr"; 435 arm,scatter-gather; 436 clocks = <&clock ATCLK>; 437 clock-names = "apb_pclk"; 438 in-ports { 439 port { 440 etr_in_port: endpoint { 441 remote-endpoint = <&funnel2_out_port>; 442 }; 443 }; 444 }; 445}; 446 447**Example 2: ETE and Coresight ETR (Pixel 8)** 448 449This example shows the device tree entries for ETE and Coresight ETR on Pixel 8 450(source: [zuma-debug.dtsi](https://android.googlesource.com/kernel/devices/google/zuma/+/refs/heads/android-gs-shusky-6.1-android16-dp/dts/zuma-debug.dtsi#428)). 451 452```device-tree 453ete0 { 454 compatible = "arm,embedded-trace-extension"; 455 cpu = <&cpu0>; 456 arm,coresight-loses-context-with-cpu; 457 out-ports { 458 port { 459 ete0_out_port: endpoint { 460 remote-endpoint = <&funnel0_in_port0>; 461 }; 462 }; 463 }; 464}; 465 466// ... ete1 to ete8, funnel0 to funnel2, etf0 ... 467 468etr: etr@2a00a000 { 469 compatible = "arm,coresight-tmc", "arm,primecell"; 470 arm,primecell-periphid = <0x001bb961>; 471 reg = <0 0x2a00a000 0x1000>; 472 coresight-name = "coresight-etr"; 473 arm,scatter-gather; 474 clocks = <&clock ATCLK>; 475 clock-names = "apb_pclk"; 476 in-ports { 477 port { 478 etr_in_port: endpoint { 479 remote-endpoint = <&funnel2_out_port>; 480 }; 481 }; 482 }; 483}; 484``` 485 486**Example 3: TRBE 487 488This example shows a basic device tree entry for TRBE. 489 490```device-tree 491trbe { 492 compatible = "arm,trace-buffer-extension"; 493 interrupts = <GIC_PPI 0 IRQ_TYPE_LEVEL_HIGH 0>; 494}; 495``` 496 497One optional flag in the ETM/ETE device tree is `arm,coresight-loses-context-with-cpu`. This flag 498ensures that ETM registers are saved when a CPU enters a low-power state. It is necessary if the 499CPU powers down the ETM/ETE during low-power states. Without this flag, the kernel cannot properly 500resume ETM data collection after the CPU wakes up, and you will likely see a 501`coresight_disclaim_device_unlocked` warning during system-wide data collection. 502 503Another optional flag in the ETR device tree is `arm,scatter-gather`. Simpleperf requires 4MB of 504contiguous system memory for the ETR to store ETM data (unless an IOMMU is present). If the kernel 505cannot provide this contiguous memory, simpleperf will report an out-of-memory error. Using the 506`arm,scatter-gather` flag allows the ETR to operate in scatter-gather mode, enabling it to utilize 507non-contiguous memory. 508 509Each CPU has an ETM device with a unique trace_id assigned by the kernel. The standard formula for 510determining the trace_id is: `trace_id = 0x10 + cpu * 2` (as defined in 511[coresight-pmu.h](https://github.com/torvalds/linux/blob/master/include/linux/coresight-pmu.h#L22)). 512If your kernel uses a different formula due to local patches, the simpleperf inject command may 513fail to parse the ETM data correctly, potentially resulting in empty output. 514 515 516### Check ETM enable status in /sys 517 518The status of ETM devices is reflected in /sys. The following is an example from a Pixel 9. 519 520```sh 521# List available Coresight devices, including ETE and TRBE. 522comet:/sys/bus/coresight/devices $ ls 523ete0 ete1 ete2 ete3 ete4 ete5 ete6 ete7 funnel0 funnel1 funnel2 tmc_etf0 tmc_etr0 524 525# Check if Coresight ETR is enabled. 526comet:/sys/bus/coresight/devices $ cat tmc_etr0/mgmt/authstatus 5270x33 528 529# Check if we have Coresight ETM/ETE devices as perf event sources. 530comet:/sys/bus/event_source/devices/cs_etm $ ls -l 531total 0 532lrwxrwxrwx 1 root root 0 2024-12-03 17:37 cpu0 -> ../platform/ete0/ete0 533lrwxrwxrwx 1 root root 0 2024-12-03 17:37 cpu1 -> ../platform/ete1/ete1 534lrwxrwxrwx 1 root root 0 2024-12-03 17:37 cpu2 -> ../platform/ete2/ete2 535lrwxrwxrwx 1 root root 0 2024-12-03 17:37 cpu3 -> ../platform/ete3/ete3 536lrwxrwxrwx 1 root root 0 2024-12-03 17:37 cpu4 -> ../platform/ete4/ete4 537lrwxrwxrwx 1 root root 0 2024-12-03 17:37 cpu5 -> ../platform/ete5/ete5 538lrwxrwxrwx 1 root root 0 2024-12-03 17:37 cpu6 -> ../platform/ete6/ete6 539lrwxrwxrwx 1 root root 0 2024-12-03 17:37 cpu7 -> ../platform/ete7/ete7 540 541# Check if we have Coresight ETR/TRBE to move ETM data to system memory. 542comet:/sys/bus/event_source/devices/cs_etm/sinks $ ls 543tmc_etf0 tmc_etr0 544``` 545 546 547## Related docs 548 549* [Arm Architecture Reference Manual for A-profile architecture, D3-D6](https://developer.arm.com/documentation/ddi0487/latest/) 550* [ARM ETM Architecture Specification](https://developer.arm.com/documentation/ihi0064/latest/) 551* [ARM CoreSight Architecture Specification](https://developer.arm.com/documentation/ihi0029/latest) 552* [CoreSight Components Technical Reference Manual](https://developer.arm.com/documentation/ddi0314/h/) 553* [CoreSight Trace Memory Controller Technical Reference Manual](https://developer.arm.com/documentation/ddi0461/b/) 554* [OpenCSD library for decoding ETM data](https://github.com/Linaro/OpenCSD) 555* [AutoFDO tool for converting profile data](https://github.com/google/autofdo) 556