Coresight是一个允许调试基于ARM的SoC技术。它包括JTAG和硬件辅助跟踪的解决方案,为实时调试和收集跟踪信息提供了系统范围的解决方案。
硬件辅助跟踪在处理具有许多SoC和其他组件(如GPU和DMA引擎)的系统时变得越来越有用。ARM通过不同的组件开发了硬件辅助跟踪解决方案,每个组件在合成时添加到设计中,以满足特定的跟踪需求。组件通常分为 source、link 和 sinks,通常使用AMBA总线进行查找。
Sources 根据用户配置的跟踪场景生成表示处理器指令路径的压缩 stream 。stream 流经CoreSight系统(通过ATB总线)使用 links 将 the emanating source 连接到 a sink(s)。Sinks充当CoreSight实施的端点,要么将压缩流存储在内存缓冲区中,要么创建到外部世界的接口,在那里数据可以传输到主机,而不必担心填满板载CoreSight内存缓冲区。
典型的CoreSight系统如下所示:
(1)多个处理器:
虽然组件的目标配置是通过APB总线完成的,但所有跟踪数据都在ATB总线上带外执行。CTM提供了一种在CoreSight组件之间聚合和分发信号的方法。
CoreSight框架提供了一个中心点来表示、配置和管理平台上的CoreSight设备。第一个实施以基本跟踪功能为中心,启用ETM/PTM、funnel、replicator、TMC、TPIU和ETB等组件。未来的工作将使更复杂的IP块,如STM和CTI。
每个逻辑处理器上都与一个ETM,CTI绑定。
(2)对于单个处理器系统中的架构图如下所示:
PTM:
Program Trace MacrocellETM:
Embedded Trace MacrocellSTM:
System trace MacrocellETB:
Embedded Trace BufferITM:
Instrumentation Trace MacrocellTPIU:
Trace Port Interface UnitTMC-ETR:
Trace Memory Controller, configured as Embedded Trace RouterTMC-ETF:
Trace Memory Controller, configured as Embedded Trace FIFOCTI:
Cross Trigger Interface
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)体系结构定义了一个实时跟踪模块,提供对处理器的指令和数据跟踪。
(3)Trace links(trace信息传递过程中所需要的中间coresight组件):
• Trace funnels.
• Replicators.
• ATB bridges.
其中Trace funnel:Trace funnel将来自所有源( sources)的跟踪合并到单个跟踪流中。
(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/
有关详细信息,请参阅Documentation/devictree/bindings/arm/arm,coresight-*.yaml。
在编写ITM驱动程序时,未提供STM和CTI,但预计将随着解决方案的成熟而添加这些驱动程序。
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”定制预计将使用这些条目进行访问和控制。
出现在“coresight”总线上的设备的名称与其父设备相同,即出现在AMBA总线或平台总线上的真实设备。因此,这些名称基于Linux开放固件层命名约定,该约定遵循设备的基本物理地址和设备类型。例如:
root:~# ls /sys/bus/coresight/devices/20010000.etf 20040000.funnel 20100000.stm 22040000.etm22140000.etm 230c0000.funnel 23240000.etm 20030000.tpiu20070000.etr 20120000.replicator 220c0000.funnel23040000.etm 23140000.etm 23340000.etm
然而,随着ACPI支持的引入,真实设备的名称有点晦涩难懂。因此,引入了一种新的命名方案,以根据设备的类型使用更多通用名称。以下规则适用:
1) 绑定到CPU的设备根据CPU逻辑号命名。
比如:绑定到CPU0的ETM被命名为“etm0”
2) 所有其他设备都遵循“
N:根据探测顺序分配的序列号。
比如:tmc_etf0, tmc_etr0, funnel0, funnel1
因此,在新的方案中,设备可以显示为:
root:~# ls /sys/bus/coresight/devices/etm0 etm1 etm2 etm3 etm4 etm5 funnel0funnel1 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 为例子来调试。
每个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时,启用接收器和源就足以成功跟踪。框架将根据需要正确启用所有中间链接。
使用CoreSight框架有两种方式:
(1)使用perf cmd行工具。
(2)使用sysFS接口直接与CoreSight设备交互。
首选前者,因为使用sysFS接口需要深入了解Coresight HW。以下各节提供了使用这两种方法的详细信息。
暂时省略
CoreSight跟踪器使用Perf框架的性能监视单元(PMU)抽象来表示。因此,Perf框架负责根据感兴趣的进程被调度的时间来控制何时启用跟踪。在系统中配置时,通过perf命令行工具查询时将列出CoreSight PMU:
root@linaro-alip:~/perf_test# ./perf list pmuList of pre-defined events (to be used in -e):cs_etm// [Kernel PMU event]
无论系统中有多少可用跟踪器(通常等于处理器核心数量),“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-threadUse 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文档)。
有关如何将CoreSight与Perf工具一起使用的上述和其他示例的更多信息,请参阅OpenCSD GitHub存储库的“HOWTO.md”文件。
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