海思 PCIe 调优和追踪设备¶
简介¶
海思 PCIe 调优和追踪设备 (PTT) 是一种 PCIe 根复合体集成端点 (RCiEP) 设备,提供动态监控和调整 PCIe 链路事件(调优)以及追踪 TLP 报头(追踪)的功能。这两个功能是独立的,但建议一起使用以分析和增强 PCIe 链路的性能。
在鲲鹏 930 SoC 上,PCIe 根复合体由多个 PCIe 核组成。每个 PCIe 核包括多个根端口和一个 PTT RCiEP,如下所示。PTT 设备能够调优和追踪 PCIe 核的链路。
+--------------Core 0-------+
| | [ PTT ] |
| | [Root Port]---[Endpoint]
| | [Root Port]---[Endpoint]
| | [Root Port]---[Endpoint]
Root Complex |------Core 1-------+
| | [ PTT ] |
| | [Root Port]---[ Switch ]---[Endpoint]
| | [Root Port]---[Endpoint] `-[Endpoint]
| | [Root Port]---[Endpoint]
+---------------------------+
PTT 设备驱动程序为每个 PTT 设备注册一个 PMU 设备。每个 PTT 设备的名称由“hisi_ptt”前缀以及它所在的 SICL 和 Core 的 ID 组成。鲲鹏 930 SoC 封装了多个 CPU 芯片(SCCL,超级 CPU 集群)和 IO 芯片(SICL,超级 I/O 集群),每个 SICL 都有一个 PCIe 根复合体。
/sys/bus/event_source/devices/hisi_ptt<sicl_id>_<core_id>
调优¶
PTT 调优旨在监控和调整 PCIe 链路参数(事件)。目前,我们支持 2 个类别的事件。事件的范围涵盖 PTT 设备所属的 PCIe 核。
每个事件都以文件形式呈现于 $(PTT PMU dir)/tune 下,并且将使用简单的打开/读取/写入/关闭循环来调优事件。
$ cd /sys/bus/event_source/devices/hisi_ptt<sicl_id>_<core_id>/tune
$ ls
qos_tx_cpl qos_tx_np qos_tx_p
tx_path_rx_req_alloc_buf_level
tx_path_tx_req_alloc_buf_level
$ cat qos_tx_dp
1
$ echo 2 > qos_tx_dp
$ cat qos_tx_dp
2
可以通过简单地从文件中读取来获取事件的当前值(数值),并将所需的值写入文件进行调优。
1. Tx 路径 QoS 控制¶
提供以下文件来调整 PCIe 核的 tx 路径的 QoS。
qos_tx_cpl: Tx 完成 TLP 的权重
qos_tx_np: Tx 非发布 TLP 的权重
qos_tx_p: Tx 发布 TLP 的权重
权重会影响 PCIe 链路上的某些数据包的比例。例如,对于存储场景,增加链路上完成数据包的比例可以增强性能,因为会消耗更多的完成数据包。
这些事件的可用调优数据为 [0, 1, 2]。写入负值将返回错误,超出范围的值将转换为 2。请注意,事件值仅表示可能的级别,但不精确。
2. Tx 路径缓冲区控制¶
提供以下文件来调整 PCIe 核的 tx 路径的缓冲区。
rx_alloc_buf_level:Rx 请求的水印
tx_alloc_buf_level:Tx 请求的水印
这些事件会影响为每种类型分配的缓冲区的水印。Rx 表示入站,而 Tx 表示出站。数据包将首先存储在缓冲区中,然后在达到水印或超时时进行传输。对于繁忙的方向,您应该增加相关的缓冲区水印,以避免频繁发布,从而提高性能。在大多数情况下,只需保留默认值即可。
上述事件的可用调优数据为 [0, 1, 2]。写入负值将返回错误,超出范围的值将转换为 2。请注意,事件值仅表示可能的级别,但不精确。
追踪¶
PTT 追踪旨在将 TLP 报头转储到内存中,这可用于分析 PCIe 链路的事务和使用情况。您可以选择通过请求者 ID 或 PTT 设备同一内核上的一组根端口的下游来过滤跟踪的报头。还支持追踪特定类型和特定方向的报头。
您可以使用 perf 命令 perf record 来设置参数、启动追踪并获取数据。还支持使用 perf report 解码追踪数据。追踪的控制参数作为每个事件的事件代码输入,稍后将进一步说明。一个用法示例是这样的
$ perf record -e hisi_ptt0_2/filter=0x80001,type=1,direction=1,
format=1/ -- sleep 5
这将追踪根端口 0000:00:10.1 的下游 TLP 报头(事件“filter”的事件代码为 0x80001),类型为已发布的 TLP 请求,方向为入站,跟踪数据格式为 8DW。
1. 筛选器¶
要追踪的 TLP 报头可以通过根端口或端点的请求者 ID 进行筛选,这些端口或端点位于 PTT 设备的同一内核上。您可以通过指定 filter 参数来设置筛选器,该参数是启动追踪所必需的。参数值为 20 位。位 19 表示筛选器类型。1 表示根端口筛选器,0 表示请求者筛选器。位 [15:0] 表示筛选器值。根端口的值是根据其 PCI 插槽 ID 计算的内核端口 ID 的掩码,计算方法为 (slotid & 7) * 2。请求者的值是请求者 ID(PCIe 功能的设备 ID)。位 [18:16] 当前保留用于扩展。
例如,如果所需的筛选器是端点功能 0000:01:00.1,则筛选器值将为 0x00101。如果所需的筛选器是根端口 0000:00:10.0,则筛选器值计算为 0x80001。
驱动程序还通过 sysfs 显示每个支持的根端口和请求者筛选器。每个筛选器都将是一个单独的文件,其名称与其相关的 PCIe 设备名称(domain:bus:device.function)相同。根端口筛选器的文件位于 $(PTT PMU dir)/root_port_filters 下,请求者筛选器的文件位于 $(PTT PMU dir)/requester_filters 下。
请注意,可以一次指定多个根端口,但在一次追踪中只能指定一个端点功能。不支持同时指定根端口和功能。驱动程序维护一个可用筛选器的列表,并将检查无效的输入。
可用的筛选器将动态更新,这意味着当发生热插拔事件或手动删除/重新扫描设备时,您将始终获得正确的筛选器信息。
2. 类型¶
您可以通过指定 type 参数来追踪特定类型的 TLP 报头,该参数是启动追踪所必需的。参数值为 8 位。当前支持的类型和相关值如下所示
8'b00000001: 发布请求 (P)
8'b00000010: 非发布请求 (NP)
8'b00000100: 完成 (CPL)
在追踪入站 TLP 报头时,您可以指定多种类型,但在追踪出站 TLP 报头时,只能指定一种类型。
3. 方向¶
您可以通过指定 direction 参数来追踪来自特定方向的 TLP 报头,该方向相对于根端口或 PCIe 核。这是可选的,默认参数为入站。参数值为 4 位。当所需格式为 4DW 时,支持的方向和相关值如下所示
4'b0000: 入站 TLP (P, NP, CPL)
4'b0001: 出站 TLP (P, NP, CPL)
4'b0010: 出站 TLP (P, NP, CPL) 和入站 TLP (P, NP, CPL B)
4'b0011: 出站 TLP (P, NP, CPL) 和入站 TLP (CPL A)
当所需格式为 8DW 时,支持的方向和相关值如下所示
4'b0000: 保留
4'b0001: 出站 TLP (P, NP, CPL)
4'b0010: 入站 TLP (P, NP, CPL B)
4'b0011: 入站 TLP (CPL A)
入站完成分为两种类型
完成 A (CPL A): CHI/DMA/原生非发布请求的完成,CPL B 除外
完成 B (CPL B): DMA remote2local 和 P2P 非发布请求的完成
4. 格式¶
您可以通过指定 format 参数来更改跟踪的 TLP 报头的格式。默认格式为 4DW。参数值为 4 位。当前支持的格式和相关值如下所示
4'b0000: 每个 TLP 报头 4DW 长度
4'b0001: 每个 TLP 报头 8DW 长度
跟踪的 TLP 报头格式与 PCIe 标准不同。
当使用 8DW 数据格式时,会记录整个 TLP 报头(如下所示的报头 DW0-3)。例如,在 PCIe r5.0 的图 2-17 中显示了具有 64 位地址的内存读取的 TLP 报头;在图 2.20 中显示了配置请求的报头,等等。
此外,8DW 跟踪缓冲区条目包含时间戳,并且可能包含 PASID TLP 前缀的前缀(请参阅 PCIe r5.0 的图 6-20)。否则,此字段将全部为 0。
DW0 的 bit[31:11] 始终为 0x1fffff,可用于区分数据格式。8DW 格式如下
bits [ 31:11 ][ 10:0 ]
|---------------------------------------|-------------------|
DW0 [ 0x1fffff ][ Reserved (0x7ff) ]
DW1 [ Prefix ]
DW2 [ Header DW0 ]
DW3 [ Header DW1 ]
DW4 [ Header DW2 ]
DW5 [ Header DW3 ]
DW6 [ Reserved (0x0) ]
DW7 [ Time ]
当使用 4DW 数据格式时,跟踪缓冲区条目的 DW0 包含 TLP 的 DW0 的选定字段,以及时间戳。跟踪缓冲区条目的 DW1-DW3 直接包含 TLP 报头的 DW1-DW3。
4DW 格式如下
bits [31:30] [ 29:25 ][24][23][22][21][ 20:11 ][ 10:0 ]
|-----|---------|---|---|---|---|-------------|-------------|
DW0 [ Fmt ][ Type ][T9][T8][TH][SO][ Length ][ Time ]
DW1 [ Header DW1 ]
DW2 [ Header DW2 ]
DW3 [ Header DW3 ]
5. 内存管理¶
跟踪的 TLP 报头将被写入驱动程序分配的内存中。硬件接受 4 个大小相同的 DMA 地址,并按如下顺序写入缓冲区。如果 DMA 地址 3 完成,并且跟踪仍在进行,它将返回到地址 0。
+->[DMA addr 0]->[DMA addr 1]->[DMA addr 2]->[DMA addr 3]-+
+---------------------------------------------------------+
驱动程序将分配每个大小为 4MiB 的 DMA 缓冲区。完成的缓冲区将被复制到 perf 核心分配的 perf AUX 缓冲区。当跟踪仍在进行时,如果 AUX 缓冲区已满,驱动程序将首先提交 AUX 缓冲区,然后申请一个新的相同大小的缓冲区。AUX 缓冲区的大小默认为 16MiB。用户可以通过指定 perf 命令的 -m 参数来调整大小。
6. 解码¶
您可以使用 perf report -D 命令解码跟踪的数据(目前仅支持转储原始跟踪数据)。跟踪的数据将按照先前描述的格式进行解码(以 8DW 为例)。
[...perf headers and other information]
. ... HISI PTT data: size 4194304 bytes
. 00000000: 00 00 00 00 Prefix
. 00000004: 01 00 00 60 Header DW0
. 00000008: 0f 1e 00 01 Header DW1
. 0000000c: 04 00 00 00 Header DW2
. 00000010: 40 00 81 02 Header DW3
. 00000014: 33 c0 04 00 Time
. 00000020: 00 00 00 00 Prefix
. 00000024: 01 00 00 60 Header DW0
. 00000028: 0f 1e 00 01 Header DW1
. 0000002c: 04 00 00 00 Header DW2
. 00000030: 40 00 81 02 Header DW3
. 00000034: 02 00 00 00 Time
. 00000040: 00 00 00 00 Prefix
. 00000044: 01 00 00 60 Header DW0
. 00000048: 0f 1e 00 01 Header DW1
. 0000004c: 04 00 00 00 Header DW2
. 00000050: 40 00 81 02 Header DW3
[...]