xref: /aosp_15_r20/system/extras/simpleperf/doc/collect_etm_data_for_autofdo.md (revision 288bf5226967eb3dac5cce6c939ccc2a7f2b4fe5)
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