海思 PCIe 调优和跟踪设备¶
简介¶
海思 PCIe 调优和跟踪设备(PTT)是一个 PCIe 根复合体集成端点(RCiEP)设备,提供动态监控和调优 PCIe 链路事件(tune),以及跟踪 TLP 报头(trace)的功能。这两个功能是独立的,但建议结合使用它们来分析和提升 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 非发布式(non-posted)TLP 的权重
qos_tx_p: Tx 发布式(posted)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(Requester 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 报头可以由位于 PTT 设备同一核心上的根端口或端点的请求者 ID 进行过滤。您可以通过指定启动跟踪所需的 filter 参数来设置过滤器。参数值为 20 位。第 19 位表示过滤器类型。1 表示根端口过滤器,0 表示请求者过滤器。Bit[15:0] 表示过滤器的值。根端口的值是核心端口 ID 的掩码,该 ID 根据其 PCI 插槽 ID 计算得出,公式为 (slotid & 7) * 2。请求者的值是请求者 ID(PCIe 功能的设备 ID)。Bit[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)。例如,带有 64 位地址的内存读取的 TLP 报头如图 PCIe r5.0 图 2-17 所示;配置请求的报头如图 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]-+
+---------------------------------------------------------+
驱动程序将为每个 DMA 缓冲区分配 4MiB。完成的缓冲区将被复制到由 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
[...]