Coresight - HW Assisted Tracing on ARM

一、Introduction

1.1 简介

Coresight是一个允许调试基于ARM的SoC技术。在ARM64架构下,CoreSight是一种硬件调试和跟踪技术。它包含多个跟踪组件,其中包括跟踪源、跟踪接收器和跟踪路由器,用于收集和传输跟踪数据。CoreSight还支持多种类型的跟踪,如指令跟踪、数据跟踪和事件跟踪,以及硬件调试功能,如断点和监视点。此外,CoreSight还提供了跟踪数据的分析工具和接口,帮助开发人员优化系统性能、调试软件,并识别问题。

在ARM64架构下,CoreSight还提供了一些新的功能和改进,如抽样跟踪、统一的跟踪组件、跟踪数据压缩、分布式调试和软件控制。这些功能可以提供更细粒度的性能分析和更高效的跟踪数据处理,并简化了系统设计和调试的复杂性。

Coresight包括JTAG和硬件辅助跟踪的解决方案,为实时调试和收集跟踪信息提供了系统范围的解决方案。

硬件辅助跟踪在处理具有许多SoC和其他组件(如GPU和DMA引擎)的系统时变得越来越有用。ARM通过不同的组件开发了硬件辅助跟踪解决方案,每个组件在合成时添加到设计中,以满足特定的跟踪需求。组件通常分为 source、link 和 sinks,通常使用AMBA总线进行查找。

Sources 根据用户配置的跟踪场景生成表示处理器指令路径的压缩流 。stream 流经CoreSight系统(通过ATB总线)使用 links 将 the emanating source 连接到 sink(s)。Sinks充当CoreSight实施的endpoints ,要么将压缩流存储在内存缓冲区中,要么创建到外部世界的接口,在那里数据可以传输到主机,而不必担心填满板载CoreSight内存缓冲区。

即:Sinks作为最后的endpoints将压缩流存储可以选择存储在内存缓冲区(处理器自我调试)中,也可以输出给外部的trace port(外部调试器)。
在这里插入图片描述
硬件跟踪产生大量的数据,通常在每秒 MB 的范围内。通过调试总线访问点、JTAG 或 CoreSight 连接器以及像 DSTREAM 这样的特殊硬件,开发人员可以访问这个庞大的跟踪数据流。DSTREAM 是一种外部硬件设备,与 ARM 开发平台和 ARM DS-5 Development Studio 中的跟踪支持进行接口连接。类似的特殊硬件也由 Lauterbach 和 Green Hills Software 提供,比如 SuperTrace Probe,它与它们各自的开发工具进行接口连接(与 ARM 一样,这些工具也是专有的)。

这些特殊的硬件设备允许开发人员通过调试接口获取系统的跟踪数据。调试接口(如 JTAG、CoreSight)提供了与目标设备的低层通信能力,从而可以读取和记录各种事件和执行轨迹。开发人员可以使用专有的开发工具(如 ARM DS-5、Lauterbach、Green Hills Software)来可视化和分析这些跟踪数据。

硬件辅助追踪:
追踪CPU core做了什么, 而且不影响CPU性能。
不用外接其他硬件。
CPU core并非必须运行Linux。

ARM 的 Coresight 和 Intel 的 PT 硬件功能一样。

1.2 CoreSight系统架构

典型的CoreSight系统如下所示:
(1)多个处理器:

在这里插入图片描述
在这里插入图片描述

虽然组件的目标配置是通过APB总线完成的,但所有跟踪数据都在ATB总线上带外执行。CTM提供了一种在CoreSight组件之间聚合和分发信号的方法。

CoreSight框架提供了一个中心点来表示、配置和管理平台上的CoreSight设备。第一个实施以基本跟踪功能为中心,启用ETM/PTM、funnel、replicator、TMC、TPIU和ETB等组件。未来的工作将使更复杂的IP块,如STM和CTI。

每个逻辑处理器上都与一个ETM,CTI绑定。

(2)对于单个处理器系统中的架构图如下所示:
在这里插入图片描述

1.3 Linux对Coresigh 框架的支持

Linux 3.19 Coresigh 框架驱动正式合入Linux内核主线,当时的介绍:

Coresight是一个技术的集合,用于调试基于ARM的SoC。ARM开发了一种硬件辅助追踪解决方案,通过不同的组件,在合成时将其添加到设计中以满足特定的追踪需求。这些组件通常被归类为源(source)、链路(link)和终点(sink),并且(通常)使用AMBA总线进行发现。"源"生成一个压缩流,表示由用户配置的追踪场景所生成的处理器指令路径。从那里,流通过Coresight系统(通过ATB总线)流动,使用连接源和终点的链路。终点作为Coresight实现的终点,可以将压缩流存储在内存缓冲区中,或者创建一个与外部世界交互的接口,使得数据可以传输到主机。

简单来说,Coresight是一种用于ARM SoC调试的技术框架。它通过使用源、链路和终点组件,以及AMBA总线,实现了处理器指令路径的追踪和数据传输。源组件生成压缩流,链路组件将流从源传输到终点,而终点组件存储或传输数据。

Linux Coresight框架为Coresight调试和跟踪驱动程序提供了一个内核接口,供其注册。它旨在基于DT规范构建Coresight组件的拓扑视图,并在启用跟踪源时配置正确的组件系列。

高版本内核Coresight框架也可以基于ACPI框架。

CoreSight驱动及其基础结构的源代码在Kernel如下目录中:

drivers/hwtracing/coresight

二、Acronyms and Classification

2.1 Acronyms

PTM:
Program Trace Macrocell

ETM:
Embedded Trace Macrocell

STM:
System trace Macrocell

ETB:
Embedded Trace Buffer

ITM:
Instrumentation Trace Macrocell

TPIU:
Trace Port Interface Unit

TMC-ETR:
Trace Memory Controller, configured as Embedded Trace Router

TMC-ETF:
Trace Memory Controller, configured as Embedded Trace FIFO

CTI:
Cross Trigger Interface

2.2 Classification

CoreSight体系结构指定了一组组件,用于实现支持调试和跟踪信息收集的特定SoC子系统。主要组件包括:

(1)Control components:
CoreSight系统包括 Embedded Cross Trigger (ECT)控制组件,ECT包括:

• A Cross Trigger Interface (CTI):每个core都有一个CTI组件相连,CTI可以给处理器发送trigger信号,也可以接收处理器的trigger信号.
• A Cross Trigger Matrix (CTM):所有的CTI和CTM相连,因此可以实现多个CTI之间的trigger信号的相互发送与接收.

trigger通路,用于给指定的组件发送trigger信号,或者接收指定的组件的trigger信号.

在这里插入图片描述

(2)Trace sources(用于产生trace数据的数据源组件):
• Embedded Trace Macrocells (ETMs).
• AMBA Trace Macrocells.
• Program Flow Trace Macrocells (PTMs).
• System Trace Macrocells (STMs).

其中ETMs:嵌入式跟踪宏单元(ETM)体系结构定义了一个实时跟踪模块,提供对处理器的指令和数据跟踪。
系统中的每个CPU core都被配置了相应的一个IP核 - Embedded Trace Macrocel (ETM)。
典型情况是每个CPU core对应一个Embedded Trace Macrocell。
系统驱动已对trace macrocell很多跟踪特性做好了配置。
被触发追踪动作之后, trace macrocells的操作都是独立。
不牵扯CPU core, 所以对CPU性能没有影响。

(3)Trace links(trace信息传递过程中所需要的中间coresight组件):
• Trace funnels.
• Replicators.
• ATB bridges.

其中Trace funnel(漏斗):Trace funnel将来自所有源( sources)的跟踪合并到单个跟踪流中。
Replicators(分发器):与Trace funnel类型,单个输入数据源,多个输出数据源。

(4)Trace sinks(最终接收trace信息的coresight组件,每个跟踪接收器可以包括一个跟踪格式化程序):
• Trace Port Interface Units (TPIUs).将数据输出给外部调试器。
• Embedded Trace Buffers (ETBs).
• Trace Memory Controllers (TMCs).
TMCs主要分为ETR和ETF组件:
•TMCs-ETR:把数据存入到SDRAM中
•TMCs-ETF:可以把数据存入到SRAM中,还可以作为链路驱动,把数据输出给下一个输入设备
在这里插入图片描述

(5)Debug Ports and Access Ports:

以我手中的高通开发板(dragonboard410c)为例:

root@linaro-alip:~# ls -l /sys/bus/coresight/devices/
cti_cpu0/    cti_cpu3/    etm0/        etm3/        replicator0/ tpiu0/
cti_cpu1/    cti_sys0/    etm1/        funnel0/     tmc_etf0/
cti_cpu2/    cti_sys1/    etm2/        funnel1/     tmc_etr0/

三、Device Tree Bindings

有关详细信息,请参阅Documentation/devictree/bindings/arm/arm,coresight-*.yaml。
比如 Documentation/devicetree/bindings/arm/arm,coresight-etm.yaml:

description: |
  CoreSight components are compliant with the ARM CoreSight architecture
  specification and can be connected in various topologies to suit a particular
  SoCs tracing needs. These trace components can generally be classified as
  sinks, links and sources. Trace data produced by one or more sources flows
  through the intermediate links connecting the source to the currently selected
  sink.

  The Embedded Trace Macrocell (ETM) is a real-time trace module providing
  instruction and data tracing of a processor.

select:
  properties:
    compatible:
      contains:
        enum:
          - arm,coresight-etm3x
          - arm,coresight-etm4x
          - arm,coresight-etm4x-sysreg
  required:
    - compatible

allOf:
  - if:
      not:
        properties:
          compatible:
            contains:
              const: arm,coresight-etm4x-sysreg
    then:
      $ref: /schemas/arm/primecell.yaml#
      required:
        - reg

properties:
  compatible:
    oneOf:
      - description:
          Embedded Trace Macrocell with memory mapped access.
        items:
          - enum:
              - arm,coresight-etm3x
              - arm,coresight-etm4x
          - const: arm,primecell
      - description:
          Embedded Trace Macrocell (version 4.x), with system register access only
        const: arm,coresight-etm4x-sysreg

  reg:
    maxItems: 1

  clocks:
    minItems: 1
    maxItems: 2

  clock-names:
    minItems: 1
    items:
      - const: apb_pclk
      - const: atclk

  power-domains:
    maxItems: 1

  arm,coresight-loses-context-with-cpu:
    type: boolean
    description:
      Indicates that the hardware will lose register context on CPU power down
      (e.g. CPUIdle). An example of where this may be needed are systems which
      contain a coresight component and CPU in the same power domain. When the
      CPU powers down the coresight component also powers down and loses its
      context.

  arm,cp14:
    type: boolean
    description:
      Must be present if the system accesses ETM/PTM management registers via
      co-processor 14.

  qcom,skip-power-up:
    type: boolean
    description:
      Indicates that an implementation can skip powering up the trace unit.
      TRCPDCR.PU does not have to be set on Qualcomm Technologies Inc. systems
      since ETMs are in the same power domain as their CPU cores. This property
      is required to identify such systems with hardware errata where the CPU
      watchdog counter is stopped when TRCPDCR.PU is set.

  cpu:
    description:
      phandle to the cpu this ETM is bound to.
    $ref: /schemas/types.yaml#/definitions/phandle

  out-ports:
    $ref: /schemas/graph.yaml#/properties/ports
    additionalProperties: false

    properties:
      port:
        description: Output connection from the ETM to CoreSight Trace bus.
        $ref: /schemas/graph.yaml#/properties/port

required:
  - compatible
  - clocks
  - clock-names
  - cpu
  - out-ports

unevaluatedProperties: false

examples:
  - |
    ptm@2201c000 {
        compatible = "arm,coresight-etm3x", "arm,primecell";
        reg = <0x2201c000 0x1000>;

        cpu = <&cpu0>;
        clocks = <&oscclk6a>;
        clock-names = "apb_pclk";
        out-ports {
            port {
                ptm0_out_port: endpoint {
                    remote-endpoint = <&funnel_in_port0>;
                };
            };
        };
    };

    ptm@2201d000 {
        compatible = "arm,coresight-etm3x", "arm,primecell";
        reg = <0x2201d000 0x1000>;

        cpu = <&cpu1>;
        clocks = <&oscclk6a>;
        clock-names = "apb_pclk";
        out-ports {
            port {
                ptm1_out_port: endpoint {
                    remote-endpoint = <&funnel_in_port1>;
                };
            };
        };
    };
...

或者参考:https://blog.csdn.net/weixin_45030965/article/details/128904115

四、Framework and implementation

coresight框架提供了在平台上表示、配置和管理coresight设备的中心点。只要使用正确的API,任何符合coresight的设备都可以在框架中注册:
(1)coresight_register

struct coresight_device *coresight_register(struct coresight_desc *desc);
/**
 * struct coresight_desc - description of a component required from drivers
 * @type:	as defined by @coresight_dev_type.
 * @subtype:	as defined by @coresight_dev_subtype.
 * @ops:	generic operations for this component, as defined
 *		by @coresight_ops.
 * @pdata:	platform data collected from DT.
 * @dev:	The device entity associated to this component.
 * @groups:	operations specific to this component. These will end up
 *		in the component's sysfs sub-directory.
 * @name:	name for the coresight device, also shown under sysfs.
 * @access:	Describe access to the device
 */
struct coresight_desc {
	enum coresight_dev_type type;
	union coresight_dev_subtype subtype;
	const struct coresight_ops *ops;
	struct coresight_platform_data *pdata;
	struct device *dev;
	const struct attribute_group **groups;
	const char *name;
	struct csdev_access access;
};

注册函数采用 struct coresight_desc *desc ,并将设备注册到核心框架。

(2)coresight_unregister

void coresight_unregister(struct coresight_device *csdev);
/**
 * struct coresight_device - representation of a device as used by the framework
 * @pdata:	Platform data with device connections associated to this device.
 * @type:	as defined by @coresight_dev_type.
 * @subtype:	as defined by @coresight_dev_subtype.
 * @ops:	generic operations for this component, as defined
 *		by @coresight_ops.
 * @access:	Device i/o access abstraction for this device.
 * @dev:	The device entity associated to this component.
 * @refcnt:	keep track of what is in use.
 * @orphan:	true if the component has connections that haven't been linked.
 * @enable:	'true' if component is currently part of an active path.
 * @activated:	'true' only if a _sink_ has been activated.  A sink can be
 *		activated but not yet enabled.  Enabling for a _sink_
 *		happens when a source has been selected and a path is enabled
 *		from source to that sink.
 * @ea:		Device attribute for sink representation under PMU directory.
 * @def_sink:	cached reference to default sink found for this device.
 * @ect_dev:	Associated cross trigger device. Not part of the trace data
 *		path or connections.
 * @nr_links:   number of sysfs links created to other components from this
 *		device. These will appear in the "connections" group.
 * @has_conns_grp: Have added a "connections" group for sysfs links.
 * @feature_csdev_list: List of complex feature programming added to the device.
 * @config_csdev_list:  List of system configurations added to the device.
 * @cscfg_csdev_lock:	Protect the lists of configurations and features.
 * @active_cscfg_ctxt:  Context information for current active system configuration.
 */
struct coresight_device {
	struct coresight_platform_data *pdata;
	enum coresight_dev_type type;
	union coresight_dev_subtype subtype;
	const struct coresight_ops *ops;
	struct csdev_access access;
	struct device dev;
	atomic_t *refcnt;
	bool orphan;
	bool enable;	/* true only if configured as part of a path */
	/* sink specific fields */
	bool activated;	/* true only if a sink is part of a path */
	struct dev_ext_attribute *ea;
	struct coresight_device *def_sink;
	/* cross trigger handling */
	struct coresight_device *ect_dev;
	/* sysfs links between components */
	int nr_links;
	bool has_conns_grp;
	bool ect_enabled; /* true only if associated ect device is enabled */
	/* system configuration and feature lists */
	struct list_head feature_csdev_list;
	struct list_head config_csdev_list;
	spinlock_t cscfg_csdev_lock;
	void *active_cscfg_ctxt;
};

unregister函数引用在注册时获得的 struct coresight_device *csdev 。

如果注册过程中一切顺利,新设备将显示在/sys/bus/coresight/devices下,如TC2平台所示:

root:~# ls /sys/bus/coresight/devices/
replicator  20030000.tpiu    2201c000.ptm  2203c000.etm  2203e000.etm
20010000.etb         20040000.funnel  2201d000.ptm  2203d000.etm

函数采用结构coresight_device,如下所示:

/**
 * struct coresight_desc - description of a component required from drivers
 * @type:	as defined by @coresight_dev_type.
 * @subtype:	as defined by @coresight_dev_subtype.
 * @ops:	generic operations for this component, as defined
 *		by @coresight_ops.
 * @pdata:	platform data collected from DT.
 * @dev:	The device entity associated to this component.
 * @groups:	operations specific to this component. These will end up
 *		in the component's sysfs sub-directory.
 * @name:	name for the coresight device, also shown under sysfs.
 * @access:	Describe access to the device
 */
struct coresight_desc {
	enum coresight_dev_type type;
	union coresight_dev_subtype subtype;
	const struct coresight_ops *ops;
	struct coresight_platform_data *pdata;
	struct device *dev;
	const struct attribute_group **groups;
	const char *name;
	struct csdev_access access;
};

“coresight_dev_type”标识设备是什么,即 source link or sink ,而“coresight _dev_subtype”将进一步描述该类型。

enum coresight_dev_type {
	CORESIGHT_DEV_TYPE_NONE,
	CORESIGHT_DEV_TYPE_SINK,
	CORESIGHT_DEV_TYPE_LINK,
	CORESIGHT_DEV_TYPE_LINKSINK,
	CORESIGHT_DEV_TYPE_SOURCE,
	CORESIGHT_DEV_TYPE_HELPER,
	CORESIGHT_DEV_TYPE_ECT,
};
/**
 * union coresight_dev_subtype - further characterisation of a type
 * @sink_subtype:	type of sink this component is, as defined
 *			by @coresight_dev_subtype_sink.
 * @link_subtype:	type of link this component is, as defined
 *			by @coresight_dev_subtype_link.
 * @source_subtype:	type of source this component is, as defined
 *			by @coresight_dev_subtype_source.
 * @helper_subtype:	type of helper this component is, as defined
 *			by @coresight_dev_subtype_helper.
 * @ect_subtype:        type of cross trigger this component is, as
 *			defined by @coresight_dev_subtype_ect
 */
union coresight_dev_subtype {
	/* We have some devices which acts as LINK and SINK */
	struct {
		enum coresight_dev_subtype_sink sink_subtype;
		enum coresight_dev_subtype_link link_subtype;
	};
	enum coresight_dev_subtype_source source_subtype;
	enum coresight_dev_subtype_helper helper_subtype;
	enum coresight_dev_subtype_ect ect_subtype;
};

struct coresight_ops 是必需的,它将告诉框架如何执行与组件相关的基本操作,每个组件都有不同的需求集。对于该结构coresight_ops_sink,已经提供了结构coresight _ops_link和结构coresigght _ops_source。

struct coresight_ops {
	const struct coresight_ops_sink *sink_ops;
	const struct coresight_ops_link *link_ops;
	const struct coresight_ops_source *source_ops;
	const struct coresight_ops_helper *helper_ops;
	const struct coresight_ops_ect *ect_ops;
};

下一个字段struct coresight_platform_dataupdate通过调用_get_coresight_platform_data()获取,作为驱动程序的_probe例程的一部分,struct devicedev获取嵌入在amba_device中的设备引用:

static int etm_probe(struct amba_device *adev, const struct amba_id *id)
{
 ...
 ...
 drvdata->dev = &adev->dev;
 ...
}

特定类别的设备(源、链接或接收器)具有可以对其执行的通用操作(请参阅结构coresight_ops)。**组是仅与特定于该组件的操作相关的sysfs条目列表。“Implementation defined”定制预计将使用这些条目进行访问和控制。

五、Device Naming scheme

出现在“coresight”总线上的设备的名称与其父设备相同,即出现在AMBA总线或平台总线上的真实设备。因此,这些名称基于Linux开放固件层命名约定,该约定遵循设备的基本物理地址和设备类型。例如:

root:~# ls /sys/bus/coresight/devices/
 20010000.etf  20040000.funnel      20100000.stm     22040000.etm
 22140000.etm  230c0000.funnel      23240000.etm     20030000.tpiu
 20070000.etr  20120000.replicator  220c0000.funnel
 23040000.etm  23140000.etm         23340000.etm

然而,随着ACPI支持的引入,真实设备的名称有点晦涩难懂。因此,引入了一种新的命名方案,以根据设备的类型使用更多通用名称。以下规则适用:
1) 绑定到CPU的设备根据CPU逻辑号命名。
比如:绑定到CPU0的ETM被命名为“etm0”

2) 所有其他设备都遵循“<device_type_prefix>N”模式,其中:
<device_type_prefix>:特定于设备类型的前缀。
N:根据探测顺序分配的序列号。
比如:tmc_etf0, tmc_etr0, funnel0, funnel1

因此,在新的方案中,设备可以显示为:

root:~# ls /sys/bus/coresight/devices/
 etm0     etm1     etm2         etm3  etm4      etm5      funnel0
 funnel1  funnel2  replicator0  stm0  tmc_etf0  tmc_etr0  tpiu0

下面的一些示例可能会引用旧的命名方案,而另一些可能引用较新的命名方案,以确认您在系统上看到的内容并不意外。用户必须使用出现在系统指定位置下的“名称”。

我手中的高通开发板 DragonBoard 410c 如下所示:

root@linaro-alip:~# ls /sys/bus/coresight/devices/
cti_cpu0  cti_cpu2  cti_sys0  etm0  etm2  funnel0  replicator0  tmc_etf0  tpiu0
cti_cpu1  cti_cpu3  cti_sys1  etm1  etm3  funnel1  stm0         tmc_etr0

接下来我就以我手中的开发版 DragonBoard 410c 为例子来调试。

六、Topology Representation

每个CoreSight组件都有一个连接目录,其中包含指向其他CoreSight组件的链接。这允许用户探索跟踪拓扑,并对于较大的系统,确定给定源的最合适接收器。连接信息还可用于确定哪些CTI设备连接到给定组件。该目录包含一个nr_Links属性,该属性详细说明了目录中的链接数量。
对于ETM源,对于高通平台上的etm0,典型的安排是:

root@linaro-alip:~# ls -l /sys/bus/coresight/devices/etm0/connections/
total 0
lrwxrwxrwx 1 root root    0 Nov 19 21:51 cti_cpu0 -> ../../../858000.cti/cti_cpu0
-r--r--r-- 1 root root 4096 Nov 19 21:51 nr_links
lrwxrwxrwx 1 root root    0 Nov 19 21:51 out:0 -> ../../../841000.funnel/funnel1

从出口到 funnel1 :

root@linaro-alip:~# ls -l /sys/bus/coresight/devices/funnel1/connections/
total 0
lrwxrwxrwx 1 root root    0 Jan  1 02:46 in:0 -> ../../../85c000.etm/etm0
lrwxrwxrwx 1 root root    0 Jan  1 02:46 in:1 -> ../../../85d000.etm/etm1
lrwxrwxrwx 1 root root    0 Jan  1 02:46 in:2 -> ../../../85e000.etm/etm2
lrwxrwxrwx 1 root root    0 Jan  1 02:46 in:3 -> ../../../85f000.etm/etm3
-r--r--r-- 1 root root 4096 Jan  1 02:46 nr_links
lrwxrwxrwx 1 root root    0 Jan  1 02:46 out:0 -> ../../../821000.funnel/funnel0

然后从出口再到 funnel0:

root@linaro-alip:~# ls -l /sys/bus/coresight/devices/funnel0/connections/
total 0
lrwxrwxrwx 1 root root    0 Jan  1 02:53 in:4 -> ../../../841000.funnel/funnel1
-r--r--r-- 1 root root 4096 Jan  1 02:53 nr_links
lrwxrwxrwx 1 root root    0 Jan  1 02:53 out:0 -> ../../../825000.etf/tmc_etf0

查找第一个接收器(sink)tmc_etf0,这可以用来作为接收器收集数据,或用作沿着链进一步传播的链接:

root@linaro-alip:~# ls -l /sys/bus/coresight/devices/tmc_etf0/connections/
total 0
lrwxrwxrwx 1 root root    0 Jan  1 03:06 in:0 -> ../../../821000.funnel/funnel0
-r--r--r-- 1 root root 4096 Jan  1 03:06 nr_links
lrwxrwxrwx 1 root root    0 Jan  1 03:06 out:0 -> ../../../824000.replicator/replicator0

replicator0:

root@linaro-alip:~# ls -l /sys/bus/coresight/devices/replicator0/connections/
total 0
lrwxrwxrwx 1 root root    0 Jan  1 03:09 in:0 -> ../../../825000.etf/tmc_etf0
-r--r--r-- 1 root root 4096 Jan  1 03:09 nr_links
lrwxrwxrwx 1 root root    0 Jan  1 03:09 out:0 -> ../../../826000.etr/tmc_etr0
lrwxrwxrwx 1 root root    0 Jan  1 03:09 out:1 -> ../../../820000.tpiu/tpiu0

到达链中的最后一个接收器,tpiu0:

root@linaro-alip:~# ls -l /sys/bus/coresight/devices/tpiu0/connections/
total 0
lrwxrwxrwx 1 root root    0 Jan  1 03:10 in:0 -> ../../../824000.replicator/replicator0
-r--r--r-- 1 root root 4096 Jan  1 03:10 nr_links
etm0
	-->cti_cpu0
		-->funnel1
			-->funnel0
				-->tmc_etf0
					-->replicator0
						-->tpiu0

如下所述,当使用sysf时,启用接收器和源就足以成功跟踪。框架将根据需要正确启用所有中间链接。

七、How to use the tracer modules

使用CoreSight框架有两种方式:
(1)使用perf cmd行工具。
(2)使用sysFS接口直接与CoreSight设备交互。
首选前者,因为使用sysFS接口需要深入了解Coresight HW。以下各节提供了使用这两种方法的详细信息。

备注:
在CoreSight框架合入Linux内核主线早期,通过Perf(AUX数据)将跟踪数据从内核传输到用户空间的基础设施并不存在,将跟踪数据的配置和获取留给了sysfs。
因此早期获取跟踪数据的配置和获取是通过sysf接口。

现在Perf(AUX数据)将跟踪数据从内核传输到用户空间的基础设施比较完善,将现有的CoreSight框架驱动程序与Perf框架进行集成,可以使用 perf 接口 来使用CoreSight框架。

7.1 Using the sysFS interface

暂时省略

7.2 Using perf framework

7.2.1 Perf支持CoreSight的实现

相比于Intel pt 和 Intel bts 在Linux内核主线4.2 perf 支持,Linux内核主线4.9 perf 才支持 CoreSight:

Add support for interacting with Coresight PMU ETMs/PTMs, that are IP blocks to perform hardware assisted tracing on a ARM CPU core

这个补丁集旨在将 Coresight 跟踪器的配置和控制与 perf 子系统集成。

其目标是使用 PMU 来表示跟踪器,并使用辅助缓冲区增强功能来收集处理器跟踪数据。因此,需要进行大量工作,将当前基于 Coresight sysFS 的配置和控制命令移植到 perf 的 AUX API 中。

目前,重点放在 ETMv3 和 ETB1.0 接收器缓冲区上。一旦建立了基础,将进一步开展 ETMv4 和其他类型接收器缓冲区的工作。

该补丁集的目标是通过 perf 子系统统一配置和控制 Coresight 跟踪器,以提供更强大和灵活的跟踪功能。通过使用 PMU 和辅助缓冲区,可以更好地集成和管理跟踪器,并通过 perf 工具进行配置和控制。

(1)perf tools: Confine __get_cpuid() to x86 architecture
该补丁旨在将 __get_cpuid() 函数限定在 x86 架构中的 perf 工具中。这个修改的目的是确保只在编译 x86 架构时才执行 __get_cpuid() 的测试,因为它所检查的功能是特定于 x86 的。

该补丁承认,当编译其他架构如 ARM 或 ARM64 时,__get_cpuid() 的测试将失败,即使在这些架构上并不需要它所检查的功能。为了解决这个问题,该补丁将内建特性检查限定在 x86 平台上,允许在其他架构(例如 ARM CoreSight)上编译和使用使用 AUXTRACE 基础设施的 PMU。

总结而言,该补丁确保 __get_cpuid() 的测试仅限于 x86 架构,允许 perf 工具在非 x86 架构上编译和使用依赖 AUXTRACE 基础设施的 PMU。

(2)perf tools: Make coresight PMU listable

该补丁旨在增加必要的机制,以使 perf list pmu 命令能够发现 Coresight ETM/PTM 跟踪器。

该补丁的作用是扩展 perf list pmu 命令的功能,使其能够识别和列出系统中可用的 Coresight ETM/PTM 跟踪器。这样,开发人员可以通过运行 perf list pmu 命令来查看系统上可用的跟踪器,以便选择适合自己需求的跟踪器进行性能分析和调试。

通过此补丁,perf 工具的功能得到了扩展,使其能够更好地支持 ARM 架构上的硬件调试和跟踪工作,提供更全面的性能分析能力。

(3)perf tools: Add coresight etm PMU record capabilities

该补丁旨在为 perf 工具添加对 Coresight ETM(Embedded Trace Macrocell)的 PMU(Performance Monitoring Unit)记录功能。

Coresight ETM 是一种用于 CPU 核心的硬件辅助跟踪的 IP 块。该补丁引入了必要的辅助 API 函数,使 perf 核心能够与跟踪器进行交互。

通过此补丁,perf 工具获得了与 Coresight ETM 跟踪器进行交互的能力。这意味着 perf 工具可以利用 Coresight ETM 来执行硬件辅助的跟踪,收集和记录 CPU 核心执行过程中的跟踪信息。

(4)perf tools: Add infrastructure for PMU specific configuration

(5)perf pmu: Push configuration down to PMU driver

(6)perf tools: Add PMU configuration to tools

(7)perf tools: Add sink configuration for cs_etm PMU

该补丁旨在为 cs_etm PMU(CoreSight Embedded Trace Macrocell)添加 sink(接收器)配置功能。通过使用 PMU::set_drv_config() 回调函数来启用用于跟踪会话的 CoreSight 接收器。

使用这个补丁,可以通过设置 cs_etm PMU 的 drv_config 配置项来配置 CoreSight 接收器。通过 PMU::set_drv_config() 回调函数,可以向 cs_etm PMU 传递特定的配置,以启用适当的 CoreSight 接收器,并将其用于跟踪会话。

通过这个补丁,perf 工具可以在启动跟踪会话时配置 cs_etm PMU 的 sink,以确保跟踪数据正确地传输到指定的 CoreSight 接收器。

7.2.2 CoreSight 和 Perf集成

(1)Perf 可谓无处不在, 有很好的说明文档, 也被Linux开发者们大量地使用

(2) Perf 有一套专为系统追踪而设计的框架

(3) 将大部分CoreSight固有的复杂性封装起来对用户隐藏

(4) 提供了便于将系统追踪的解码功能集成的工具
不用处理那个 “metadata”

(5) Trace Macrocell 对于Perf core来讲就是PMU (Performance Monitor Unit)
非常紧密的控制跟踪动作何时开始和结束
绘制跟踪数据时可以在用户空间和内核空间之间做到零拷贝

(6) 注册PMU是在CoreSight公共框架中完成的 → (不需要介入)

(7) CoreSight PMU在Perf core中的名字是cs_etm.

// include/linux/coresight-pmu.h

#define CORESIGHT_ETM_PMU_NAME "cs_etm"
// /drivers/hwtracing/coresight/coresight-etm-perf.c

static struct pmu etm_pmu;

int __init etm_perf_init(void)
{
	int ret;

	etm_pmu.capabilities		= (PERF_PMU_CAP_EXCLUSIVE |
					   PERF_PMU_CAP_ITRACE);

	etm_pmu.attr_groups		= etm_pmu_attr_groups;
	etm_pmu.task_ctx_nr		= perf_sw_context;
	etm_pmu.read			= etm_event_read;
	etm_pmu.event_init		= etm_event_init;
	etm_pmu.setup_aux		= etm_setup_aux;
	etm_pmu.free_aux		= etm_free_aux;
	etm_pmu.start			= etm_event_start;
	etm_pmu.stop			= etm_event_stop;
	etm_pmu.add			= etm_event_add;
	etm_pmu.del			= etm_event_del;
	etm_pmu.addr_filters_sync	= etm_addr_filters_sync;
	etm_pmu.addr_filters_validate	= etm_addr_filters_validate;
	etm_pmu.nr_addr_filters		= ETM_ADDR_CMP_MAX;
	etm_pmu.module			= THIS_MODULE;

	ret = perf_pmu_register(&etm_pmu, CORESIGHT_ETM_PMU_NAME, -1);
	if (ret == 0)
		etm_perf_up = true;

	return ret;
}

调用 perf_pmu_register() 会创建一个具备参数中指定的 _struct pmu 特征的新 PMU。当成功注册完成后,新的 PMU 将与在启动时编目的其他 PMU 并列。

通过调用 perf_pmu_register(),可以动态地向系统添加新的 PMU,并扩展性能监测的功能。这使得可以根据实际需求和硬件支持,灵活地配置和选择适当的 PMU 进行性能分析和调试。

7.2.3 perf使用CoreSigh框架

CoreSight跟踪器使用Perf框架的性能监视单元(PMU)抽象来表示。因此,Perf框架负责根据感兴趣的进程被调度的时间来控制何时启用跟踪。在系统中配置时,通过perf命令行工具查询时将列出CoreSight PMU:

root@linaro-alip:~/perf_test# ./perf list pmu

List of pre-defined events (to be used in -e):
  cs_etm//                                           [Kernel PMU event]

ARM64处理器其他的PMU事件:

root@linaro-alip:~# cat /sys/bus/event_source/devices/
armv8_cortex_a53/ breakpoint/       cs_etm/           software/

cs_etm PMU事件:

root@linaro-alip:~# cat /sys/bus/event_source/devices/cs_etm/
cpu0/                       perf_event_mux_interval_ms
cpu1/                       power/
cpu2/                       sinks/
cpu3/                       subsystem/
events/                     type
format/                     uevent
nr_addr_filters
root@linaro-alip:~# ls -l /sys/devices/cs_etm/
cpu0/                       perf_event_mux_interval_ms
cpu1/                       power/
cpu2/                       sinks/
cpu3/                       subsystem/
events/                     type
format/                     uevent
nr_addr_filters

无论系统中有多少可用跟踪器(通常等于处理器核心数量),“cs_etm”PMU都将只列出一次。CoreSight PMU的工作方式与任何其他PMU相同,即PMU的名称与配置选项一起列在正斜杠‘/’内。由于CoreSight系统通常具有多个接收器,因此需要将要使用的接收器的名称指定为事件选项。在较新的内核上,可用接收器列在($SYSFS)/bus/event_source/devices/cs_etm/sinks/:下的sysFS中:

root@linaro-alip:/sys/bus/event_source/devices/cs_etm/sinks# ls
tmc_etf0  tmc_etr0  tpiu0

正斜杠‘/’中的语法很重要。‘@’字符告诉解析器(the parser)即将指定接收器(sink ),并且这是用于跟踪会话的接收器。

perf可用于记录和分析程序的跟踪。
可以使用带有cs_etm事件的‘perf record’记录执行,指定要记录到的接收器的名称,例如:

perf record -e cs_etm/@tmc_etr0/u --per-thread
 perf-record - Run a command and record its profile into perf.data

该命令将其中的性能计数器配置文件收集到Perform.data中,并且该命令不显示任何内容。

-e, --event=
           Select the PMU event. 
--per-thread
           Use per-thread mmaps. By default per-cpu mmaps are created. This option overrides that and uses per-thread mmaps.

“perf report”和“perf script”命令可用于分析执行、合成指令跟踪中的指令和分支事件。”perf-inject”可用于用合成事件替换跟踪数据。–itrace选项控制合成事件的类型和频率(请参阅perf文档)。

八、OpenCSD

OpenCSD库是一个强大的工具,旨在解码通过CoreSight跟踪硬件生成的跟踪数据流。

有关如何将CoreSight与Perf工具一起使用的上述和其他示例的更多信息,请参阅OpenCSD GitHub存储库的“HOWTO.md”文件。

Open CoreSight Decoding library (开源CoreSight解码库)简称OpenCSD,用于追踪数据解码。一项由Texas Instrument, ARM and Linaro联合开发的工作,免费且开源的Program Flow Traces的解码方案。

OpenCSD已经完全和Perf集成了,OpenCSD 库需要与Perf工具链接在一起。如果Perf和OpenCSD没有联在一起用, 将做不了追踪数据的解码。

CoreSight 和 openCSD 已经和Perf子系统集成好了。有意地让在CoreSight上进行的Perf操作和在Intel PT上一样。

在用户空间,集成主要围绕三个工具进行:perf record、perf report和perf script,这些都是我们一直在提到的perf子命令。其中,perf record用于事件配置和创建,而后两者用于将会话期间收集的跟踪数据以人类可读的格式呈现。

8.1 perf record

在perf record子命令中的集成是通过提供一个特定于架构的函数来完成的,该函数返回一个struct auxtrace_record结构体。与内核 PMU 抽象类似,auxtrace_record结构体允许通用核心执行特定于架构的操作,而不会失去通用性。这样就可以处理由 IntePT 和 CoreSight 生成的跟踪数据,而无需对通用核心进行任何更改。

除其他功能外,提供给struct auxtrace_record的函数处理以下事项:如何查找特定跟踪器的元数据、在perf.data文件中呈现和格式化元数据,以及与内核和用户空间之间共享的环形缓冲区的大小和映射相关的细节。然后,该环形缓冲区用于从内核中检索跟踪数据。

8.2 perf report and perf script

在perf report和perf script工具中进行跟踪数据的解压缩和呈现。该过程始于读取perf.data文件,并解析在跟踪会话期间生成的每个事件。其中,AUXTRACEINFO和PERF_RECORD_MMAP2事件尤为重要。第一个事件携带了关于跟踪器配置的丰富信息,即所谓的元数据,以及在perf.data文件中定位跟踪数据块的偏移量列表。这些偏移量被记录下来以供后续处理。

PERF_RECORD_MMAP2事件携带了在跟踪会话期间加载/执行的二进制文件和库的名称和路径。这些通常被称为动态共享对象(Dynamic Shared Object,DSO)。对于跟踪解码来说,掌握这些 DSO 是很重要的,因为某些分支点不携带目标地址,只表明分支点是否被执行。在这些情况下,需要读取代码以确定执行恢复的位置。

一旦收集到所有这些信息,就可以开始解码跟踪数据。该过程是通过将先前记录的跟踪数据偏移量提供给解码器来完成的。解码器是由 openCSD companion 库提供的实例化对象。它逐步解码跟踪数据块,并在每一轮成功解码之后调用用户提供的回调函数。

在基础设施调试方面,原始跟踪数据包输出(在这种情况下为 ETMv4)非常有用,但在系统故障排除场景中的价值有限。这些数据包会通过 OpenCSD 库进一步解码为一组通用数据包,描述核心状态和执行的指令范围。perf report和perf script命令将从解码器获取返回的数据包,并对与执行的指令范围相关的数据包进行过滤,并进行统计和合成。在 Perf 的术语中,合成过程涉及如何将解码和相关事件呈现给用户。

在内核空间中,CoreSight 跟踪器的配置和控制函数被整合到 PMU 接口中,使得 Perf 核心能够以与其他系统监控指标相同的方式控制跟踪数据的生成。在用户空间中,有价值的元数据以及跟踪会话的数据块从perf.data文件中提取出来,并提交给解码器openCSD进行数据包提取。根据所需的详细级别,可以提供不同的合成方法,例如使用perf report命令生成流行的火焰图,而更详细的分析可以通过 Python 或 Perl 脚本呈现。

OpenCSD – Operation and Use of the Library 将详细介绍 OpenCSD 库。文章将介绍不同的组件以及如何使用它们来解码跟踪数据,以及允许与各种独立程序集成的 C++ 和 C API。还将介绍使用该库的示例和测试程序,以演示如何使用该库进行跟踪数据的处理。

参考资料

https://www.cnblogs.com/lvzh/p/16628873.html
https://static.lwn.net/kerneldoc/trace/coresight/coresight.html
https://community.arm.com/arm-community-blogs/b/architectures-and-processors-blog/posts/how-to-debug-coresight-basics-part-3
利用CoreSight 和 OpenCSD在ARM上做硬件辅助tracing
https://thenewstack.io/hardware-tracing-fast-precise-performance-analysis/
CoreSight, Perf and the OpenCSD Library

https://kernelnewbies.org/Linux_3.19
https://kernelnewbies.org/Linux_4.9

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值