系统 Trace 模块¶
系统 Trace 模块(System Trace Module,STM)是 MIPI STP 规范中描述的一种设备,用作 STP trace 流生成器。STP(System Trace Protocol,系统 Trace 协议)是一种 trace 协议,用于复用来自多个 trace 源的数据,每个 trace 源都被分配一个唯一的 master 和 channel 对。虽然其中一些 master 和 channel 是静态分配给某些硬件 trace 源的,但其他的则可供软件使用。软件 trace 源通常可以自由地从此池中为自己选择任意的 master/channel 组合。
在此 STP 流的接收端(解码器端),trace 源只能通过 master/channel 组合来识别,因此为了让解码器能够理解涉及多个 trace 源的 trace,它必须能够将这些 master/channel 对映射到它所理解的 trace 源。
例如,了解 syslog 消息来自 master 7 channel 15 会很有帮助,而任意用户应用程序可以使用 master 48 到 63 以及 channel 0 到 127。
为了解决这个映射问题,stm 类通过 configfs 提供了一种策略管理机制,允许定义将字符串标识符映射到 master 和 channel 范围的规则。如果这些规则(策略)与解码器的期望一致,它就能正确处理 trace 数据。
此策略是一个树形结构,包含规则(policy_node),这些规则具有名称(字符串标识符)以及与之关联的 master 和 channel 范围,位于 configfs 中的 “stp-policy” 子系统目录下。最顶层目录的名称(策略)格式化为应用此策略的 STM 设备名称和一个用句点分隔的任意字符串标识符。从上面的例子来看,规则可能看起来像这样
$ ls /config/stp-policy/dummy_stm.my-policy/user
channels masters
$ cat /config/stp-policy/dummy_stm.my-policy/user/masters
48 63
$ cat /config/stp-policy/dummy_stm.my-policy/user/channels
0 127
这意味着此规则的 master 分配池由 48 到 63 的 master 组成,channel 分配池包含 0 到 127 的 channel。现在,任何将自己标识为 “user” 标识字符串的生产者(trace 源)都将从这些范围内分配到一个 master 和 channel。
这些规则可以嵌套,例如,可以在上面例子中的 “user” 目录下定义一个规则 “dummy”,这个新规则将用于 id 字符串为 “user/dummy” 的 trace 源。
Trace 源必须打开 stm 类设备的节点,并将它们的 trace 数据写入其文件描述符中。
为了给给定的 trace 源找到合适的策略节点,可以使用几种机制。首先,trace 源可以在向字符设备的文件描述符写入任何数据之前,通过在其文件描述符上调用 STP_POLICY_ID_SET ioctl 并提供其 id 字符串来显式标识自己。其次,如果它们选择不进行显式标识(因为你可能不想为了这样做而修改现有软件),它们可以直接开始写入数据,此时 stm 核心将尝试查找名称与任务名称(例如 “syslogd”)匹配的策略节点,如果存在,则使用该节点。第三,如果在策略节点中找不到任务名称,则将使用兜底条目 “default”(如果存在的话)。该条目也需要由系统管理员或负责策略配置的任何工具来创建和配置。最后,如果上述所有步骤都失败了,对 stm 文件描述符的 write() 将返回一个错误(EINVAL)。
以前,如果找不到 trace 源的策略节点,stm 类会静默地回退到从设备 master/channel 范围的起始处分配第一个可用的连续 master/channel 范围。要求必须存在策略节点的新规定将帮助程序员和系统管理员识别配置中的漏洞,并更好地控制未标识的源。
某些 STM 设备可能允许将 channel mmio 区域直接映射到用户空间以进行零拷贝写入。一个可映射页(就 mmu 而言)通常包含多个 channel 的 mmio,因此用户需要为自己分配相应数量的 channel(通过上述 ioctl() 调用)才能做到这一点。也就是说,如果你的 stm 设备的 channel mmio 区域是 64 字节,硬件页大小是 4096 字节,在使用 width==64 成功调用 STP_POLICY_ID_SET ioctl() 后,你应该能够在此文件描述符上 mmap() 一页,并获得对 64 个 channel 的 mmio 区域的直接访问权限。
STM 设备的例子包括 Intel(R) Trace Hub [1] 和 Coresight STM [2]。
stm_source¶
对于基于内核的 trace 源,有 “stm_source” 设备类。此类设备可以在运行时通过名为 “stm_source_link” 的 sysfs 属性连接到 stm 设备或从 stm 设备断开,方法是将所需的 stm 设备名称写入其中,例如
$ echo dummy_stm.0 > /sys/class/stm_source/console/stm_source_link
有关如何在内核中使用 stm_source 接口的示例,请参考 stm_console、stm_heartbeat 或 stm_ftrace 驱动程序。
每个 stm_source 设备都需要占用一个 master 和一段 channel 范围,具体取决于它需要的 channel 数量。这些是根据策略配置为设备分配的。如果在策略目录的根目录下有一个与 stm_source 设备的名称匹配的节点(例如 “console”),则该节点将用于分配 master 和 channel 编号。如果没有这样的策略节点,stm 核心将使用兜底条目 “default”(如果存在的话)。如果这两个策略节点都不存在,对 stm_source_link 的 write() 将返回错误。
stm_console¶
该接口的一个实现(也在上面的例子中使用)是 “stm_console” 驱动程序,它基本上通过 stm 设备为内核消息提供单向控制台。
要配置将在此控制台的 STP 流中分配的 master/channel 对,请创建一个 “console” 策略条目(有关如何操作,请参阅本文开头)。初始化时,它将消耗一个 channel。
stm_ftrace¶
这是另一个 “stm_source” 设备,一旦 stm_ftrace 与 stm 设备链接,并且如果启用了 “function” 跟踪器,Ftrace 子系统将存储到环形缓冲区(ring buffer)中的函数地址和父函数地址将同时通过 stm 设备导出。
目前仅支持 Ftrace 的 “function” 跟踪器。