[RFC PATCH 00/12] Add Linux RISC-V trace support via CoreSight

Anup Patel anup at brainfault.org
Tue Apr 14 00:23:34 PDT 2026


On Tue, Apr 14, 2026 at 9:12 AM Zane Leung <liangzhen at linux.spacemit.com> wrote:
>
> From: liangzhen <zhen.liang at spacemit.com>
>
> This series adds Linux RISC-V trace support via CoreSight, implementing RISC-V
> trace drivers within the CoreSight framework and integrating them with perf tools.
> The K3 SoC contains RISC-V Encoder, Funnel, ATB, CoreSight Funnel, and CoreSight TMC
> components, which can be directly leveraged through the existing CoreSight infrastructure.
>
> Linux RISC-V trace support form Anup Patel:
> (https://patchwork.kernel.org/project/linux-riscv/cover/20260225062448.4027948-1-anup.patel@oss.qualcomm.com/)
> which currently lacks ATB component support and guidance on reusing CoreSight components.

What stops you from adding RISC-V trace funnel and ATB bridge drivers
on top of this series ?

>
> The series includes:
> - RISC-V trace driver implementation within the CoreSight framework

The RISC-V trace very different from the CoreSight framework in many ways:
1) Types of components supported
2) Trace packet formats
3) The way MMIO based components are discoverd
4) ... and more ...

> - RISC-V Trace Encoder, Funnel, and ATB Bridge drivers as CoreSight devices
> - RISC-V trace PMU record capabilities and parsing events in perf.
> - RISC-V Nexus Trace decoder for perf tools
>
> Any comments or suggestions are welcome.
>
> Verification on K3 SoC:
> To verify this patch series on K3 hardware, the following device tree are required:
> 1. RISC-V Trace Encoder node (8)
> 2. RISC-V ATB Bridge node (8)
> 3. RISC-V Trace Funnel node (2)
> 3. CoreSight Funnel configuration for RISC-V (1)
> 4. CoreSight TMC configuration for trace buffer (1)
>
> /{
>         dummy_clk: apb-pclk {
>                 compatible = "fixed-clock";
>                 #clock-cells = <0x0>;
>                 clock-output-names = "clk14mhz";
>                 clock-frequency = <14000000>;
>         };
>
>
>         soc: soc {
>                 #address-cells = <2>;
>                 #size-cells = <2>;
>
>                 encoder0: encoder at d9002000 {
>                         compatible = "riscv,trace-encoder";
>                         reg = <0x0 0xd9002000 0x0 0x1000>;
>                         cpus = <&cpu_0>;
>                         out-ports {
>                                 port {
>                                         cluster0_encoder0_out_port: endpoint {
>                                                 remote-endpoint = <&cluster0_bridge0_in_port>;
>                                         };
>                                 };
>                         };
>                 };
>
>                 bridge0: bridge at d9003000 {
>                         compatible = "riscv,trace-atbbridge";
>                         reg = <0x0 0xd9003000 0x0 0x1000>;
>                         cpus = <&cpu_0>;
>                         out-ports {
>                                 port {
>                                         cluster0_bridge0_out_port: endpoint {
>                                                 remote-endpoint = <&cluster0_funnel_in_port0>;
>                                         };
>                                 };
>                         };
>                         in-ports {
>                                 port {
>                                         cluster0_bridge0_in_port: endpoint {
>                                                 remote-endpoint = <&cluster0_encoder0_out_port>;
>                                         };
>                                 };
>                         };
>                 };
>
> ...
>
>                 cluster0_funnel: funnel at d9000000 {
>                         compatible = "riscv,trace-funnel";
>                         reg = <0x0 0xd9000000 0x0 0x1000>;
>                         cpus = <&cpu_0>, <&cpu_1>, <&cpu_2>, <&cpu_3>;
>                         riscv,timestamp-present;
>                         out-ports {
>                                 port {
>                                         cluster0_funnel_out_port: endpoint {
>                                                 remote-endpoint = <&main_funnel_in_port0>;
>                                         };
>                                 };
>                         };
>                         in-ports {
>                                 #address-cells = <1>;
>                                 #size-cells = <0>;
>
>                                 port at 0 {
>                                         reg = <0>;
>                                         cluster0_funnel_in_port0: endpoint {
>                                                 remote-endpoint = <&cluster0_bridge0_out_port>;
>                                         };
>                                 };
>
>                                 port at 1 {
>                                         reg = <1>;
>                                         cluster0_funnel_in_port1: endpoint {
>                                                 remote-endpoint = <&cluster0_bridge1_out_port>;
>                                         };
>                                 };
>
>                                 port at 2 {
>                                         reg = <2>;
>                                         cluster0_funnel_in_port2: endpoint {
>                                                 remote-endpoint = <&cluster0_bridge2_out_port>;
>                                         };
>                                 };
>
>                                 port at 3 {
>                                         reg = <3>;
>                                         cluster0_funnel_in_port3: endpoint {
>                                                 remote-endpoint = <&cluster0_bridge3_out_port>;
>                                         };
>                                 };
>                         };
>                 };
>
>                 cluster1_funnel: funnel at d9010000 {
>                         compatible = "riscv,trace-funnel";
>                         reg = <0x0 0xd9010000 0x0 0x1000>;
>                         cpus = <&cpu_4>, <&cpu_5>, <&cpu_6>, <&cpu_7>;
>                         riscv,timestamp-present;
>                         out-ports {
>                                 port {
>                                         cluster1_funnel_out_port: endpoint {
>                                                 remote-endpoint = <&main_funnel_in_port1>;
>                                         };
>                                 };
>                         };
>                         in-ports {
>                                 #address-cells = <1>;
>                                 #size-cells = <0>;
>
>                                 port at 0 {
>                                         reg = <0>;
>                                         cluster1_funnel_in_port0: endpoint {
>                                                 remote-endpoint = <&cluster1_bridge0_out_port>;
>                                         };
>                                 };
>
>                                 port at 1 {
>                                         reg = <1>;
>                                         cluster1_funnel_in_port1: endpoint {
>                                                 remote-endpoint = <&cluster1_bridge1_out_port>;
>                                         };
>                                 };
>
>                                 port at 2 {
>                                         reg = <2>;
>                                         cluster1_funnel_in_port2: endpoint {
>                                                 remote-endpoint = <&cluster1_bridge2_out_port>;
>                                         };
>                                 };
>
>                                 port at 3 {
>                                         reg = <3>;
>                                         cluster1_funnel_in_port3: endpoint {
>                                                 remote-endpoint = <&cluster1_bridge3_out_port>;
>                                         };
>                                 };
>                         };
>                 };
>
>                 main_funnel: funnel at d9042000 {
>                         compatible = "arm,coresight-dynamic-funnel", "arm,primecell";

Is it legally allowed to mix and match ARM coresight IPs with
RISC-V trace components at hardware level ?

>                         reg = <0x0 0xd9042000 0x0 0x1000>;
>                         clocks = <&dummy_clk>;
>                         clock-names = "apb_pclk";
>                         out-ports {
>                                 port {
>                                         main_funnel_out_port: endpoint {
>                                                 remote-endpoint = <&etf_in_port>;
>                                         };
>                                 };
>                         };
>                         in-ports {
>                                 #address-cells = <1>;
>                                 #size-cells = <0>;
>
>                                 port at 0 {
>                                         reg = <0>;
>                                         main_funnel_in_port0: endpoint {
>                                                 remote-endpoint = <&cluster0_funnel_out_port>;
>                                         };
>                                 };
>
>                                 port at 1 {
>                                         reg = <1>;
>                                         main_funnel_in_port1: endpoint {
>                                                 remote-endpoint = <&cluster1_funnel_out_port>;
>                                         };
>                                 };
>                         };
>                 };
>
>                 etf: etf at d9043000 {
>                         compatible = "arm,coresight-tmc", "arm,primecell";
>                         reg = <0x0 0xd9043000 0x0 0x1000>;
>                         clocks = <&dummy_clk>;
>                         clock-names = "apb_pclk";
>                         out-ports {
>                                 port {
>                                         etf_out_port: endpoint {
>                                                 remote-endpoint = <&etr_in_port>;
>                                         };
>                                 };
>                         };
>                         in-ports {
>                                 port {
>                                         etf_in_port: endpoint {
>                                                 remote-endpoint = <&main_funnel_out_port>;
>                                         };
>                                 };
>                         };
>                 };
>
>                 etr: etr at d9044000 {
>                         compatible = "arm,coresight-tmc", "arm,primecell";
>                         reg = <0x0 0xd9044000 0x0 0x1000>;
>                         clocks = <&dummy_clk>;
>                         clock-names = "apb_pclk";
>                         arm,scatter-gather;
>                         in-ports {
>                                 port {
>                                         etr_in_port: endpoint {
>                                                 remote-endpoint = <&etf_out_port>;
>                                         };
>                                 };
>                         };
>                 };
>         };
> };
>
> Verification case:
>
> ~ # perf list pmu
>   rvtrace//                                          [Kernel PMU event]
>
> ~ # perf record -e rvtrace/@tmc_etr0/ --per-thread uname
> Linux
> [ perf record: Woken up 1 times to write data ]
> [ perf record: Captured and wrote 0.191 MB perf.data ]
> ~ # perf script
>            uname     137 [003]          1           branches:  ffffffff80931470 rvtrace_poll_bit+0x38 ([kernel.kallsyms]) => ffffffff80931492 rvtrace_poll_bit+0x5a ([kernel.kallsyms])
>            uname     137 [003]          1           branches:  ffffffff809328a6 encoder_enable_hw+0x252 ([kernel.kallsyms]) => ffffffff809328ba encoder_enable_hw+0x266 ([kernel.kallsyms])
>            uname     137 [003]          1           branches:  ffffffff80932c4a encoder_enable+0x82 ([kernel.kallsyms]) => ffffffff80932c36 encoder_enable+0x6e ([kernel.kallsyms])
>            uname     137 [003]          1           branches:  ffffffff80928198 etm_event_start+0xf0 ([kernel.kallsyms]) => ffffffff809281aa etm_event_start+0x102 ([kernel.kallsyms])
>            uname     137 [003]          1           branches:  ffffffff809281e6 etm_event_start+0x13e ([kernel.kallsyms]) => ffffffff8092755e coresight_get_sink_id+0x16 ([kernel.kallsyms])
>            uname     137 [003]          1           branches:  ffffffff8092820e etm_event_start+0x166 ([kernel.kallsyms]) => ffffffff80928226 etm_event_start+0x17e ([kernel.kallsyms])
>            uname     137 [003]          1           branches:  ffffffff801c3bb4 perf_report_aux_output_id+0x0 ([kernel.kallsyms]) => ffffffff801c3bd6 perf_report_aux_output_id+0x22 ([kernel.kallsyms])
>            uname     137 [003]          1           branches:  ffffffff801c3c5a perf_report_aux_output_id+0xa6 ([kernel.kallsyms]) => ffffffff801c3bf0 perf_report_aux_output_id+0x3c ([kernel.kallsyms])
>            uname     137 [003]          1           branches:  ffffffff801c3c40 perf_report_aux_output_id+0x8c ([kernel.kallsyms]) => ffffffff801c3aea __perf_event_header__init_id+0x2a ([kernel.kallsyms])
>            uname     137 [003]          1           branches:  ffffffff801c3b42 __perf_event_header__init_id+0x82 ([kernel.kallsyms]) => ffffffff801c3b4a __perf_event_header__init_id+0x8a ([kernel.kallsyms])
>            uname     137 [003]          1           branches:  ffffffff801c3bb0 __perf_event_header__init_id+0xf0 ([kernel.kallsyms]) => ffffffff801c3b58 __perf_event_header__init_id+0x98 ([kernel.kallsyms])
>            uname     137 [003]          1           branches:  ffffffff8004c658 __task_pid_nr_ns+0x0 ([kernel.kallsyms]) => ffffffff8004c696 __task_pid_nr_ns+0x3e ([kernel.kallsyms])
>            uname     137 [003]          1           branches:  ffffffff8004c71e __task_pid_nr_ns+0xc6 ([kernel.kallsyms]) => ffffffff8004c6a4 __task_pid_nr_ns+0x4c ([kernel.kallsyms])
>            uname     137 [003]          1           branches:  ffffffff8004c6e4 __task_pid_nr_ns+0x8c ([kernel.kallsyms]) => ffffffff8004c6e4 __task_pid_nr_ns+0x8c ([kernel.kallsyms])
> ...
>
> liangzhen (12):
>   coresight: Add RISC-V support to CoreSight tracing
>   coresight: Initial implementation of RISC-V trace driver
>   coresight: Add RISC-V Trace Encoder driver
>   coresight: Add RISC-V Trace Funnel driver
>   coresight: Add RISC-V Trace ATB Bridge driver
>   coresight rvtrace: Add timestamp component support for encoder and
>     funnel
>   coresight: Add RISC-V PMU name support
>   perf tools: riscv: making rvtrace PMU listable
>   perf tools: Add RISC-V trace PMU record capabilities
>   perf tools: Add Nexus RISC-V Trace decoder
>   perf symbols: Add RISC-V PLT entry sizes
>   perf tools: Integrate RISC-V trace decoder into auxtrace
>
>  drivers/hwtracing/Kconfig                     |    2 +
>  drivers/hwtracing/coresight/Kconfig           |   46 +-
>  drivers/hwtracing/coresight/Makefile          |    6 +
>  drivers/hwtracing/coresight/coresight-core.c  |    8 +
>  .../hwtracing/coresight/coresight-etm-perf.c  |    1 -
>  .../hwtracing/coresight/coresight-etm-perf.h  |   21 +
>  .../hwtracing/coresight/coresight-platform.c  |    1 -
>  .../hwtracing/coresight/coresight-tmc-etf.c   |    4 +
>  .../hwtracing/coresight/coresight-tmc-etr.c   |    4 +
>  .../hwtracing/coresight/rvtrace-atbbridge.c   |  239 +++
>  drivers/hwtracing/coresight/rvtrace-core.c    |  135 ++
>  .../coresight/rvtrace-encoder-core.c          |  562 +++++++
>  .../coresight/rvtrace-encoder-sysfs.c         |  363 +++++
>  drivers/hwtracing/coresight/rvtrace-encoder.h |  151 ++
>  drivers/hwtracing/coresight/rvtrace-funnel.c  |  337 ++++
>  drivers/hwtracing/coresight/rvtrace-funnel.h  |   39 +
>  .../hwtracing/coresight/rvtrace-timestamp.c   |  278 ++++
>  .../hwtracing/coresight/rvtrace-timestamp.h   |   64 +
>  include/linux/coresight-pmu.h                 |    4 +
>  include/linux/rvtrace.h                       |  116 ++
>  tools/arch/riscv/include/asm/insn.h           |  645 ++++++++
>  tools/perf/arch/riscv/util/Build              |    2 +
>  tools/perf/arch/riscv/util/auxtrace.c         |  490 ++++++
>  tools/perf/arch/riscv/util/pmu.c              |   20 +
>  tools/perf/util/Build                         |    3 +
>  tools/perf/util/auxtrace.c                    |    4 +
>  tools/perf/util/auxtrace.h                    |    1 +
>  tools/perf/util/nexus-rv-decoder/Build        |    1 +
>  .../util/nexus-rv-decoder/nexus-rv-decoder.c  | 1364 +++++++++++++++++
>  .../util/nexus-rv-decoder/nexus-rv-decoder.h  |  139 ++
>  .../perf/util/nexus-rv-decoder/nexus-rv-msg.h |  190 +++
>  tools/perf/util/rvtrace-decoder.c             | 1039 +++++++++++++
>  tools/perf/util/rvtrace.h                     |   40 +
>  tools/perf/util/symbol-elf.c                  |    4 +
>  34 files changed, 6320 insertions(+), 3 deletions(-)
>  create mode 100644 drivers/hwtracing/coresight/rvtrace-atbbridge.c
>  create mode 100644 drivers/hwtracing/coresight/rvtrace-core.c
>  create mode 100644 drivers/hwtracing/coresight/rvtrace-encoder-core.c
>  create mode 100644 drivers/hwtracing/coresight/rvtrace-encoder-sysfs.c
>  create mode 100644 drivers/hwtracing/coresight/rvtrace-encoder.h
>  create mode 100644 drivers/hwtracing/coresight/rvtrace-funnel.c
>  create mode 100644 drivers/hwtracing/coresight/rvtrace-funnel.h
>  create mode 100644 drivers/hwtracing/coresight/rvtrace-timestamp.c
>  create mode 100644 drivers/hwtracing/coresight/rvtrace-timestamp.h
>  create mode 100644 include/linux/rvtrace.h
>  create mode 100644 tools/arch/riscv/include/asm/insn.h
>  create mode 100644 tools/perf/arch/riscv/util/auxtrace.c
>  create mode 100644 tools/perf/arch/riscv/util/pmu.c
>  create mode 100644 tools/perf/util/nexus-rv-decoder/Build
>  create mode 100644 tools/perf/util/nexus-rv-decoder/nexus-rv-decoder.c
>  create mode 100644 tools/perf/util/nexus-rv-decoder/nexus-rv-decoder.h
>  create mode 100644 tools/perf/util/nexus-rv-decoder/nexus-rv-msg.h
>  create mode 100644 tools/perf/util/rvtrace-decoder.c
>  create mode 100644 tools/perf/util/rvtrace.h
>
> --
> 2.34.1
>

NACK to this approach of retrofitting RISC-V trace into ARM coresight.

Regards,
Anup



More information about the linux-riscv mailing list