海思 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 和核心的 ID 組成。鯤鵬 930 SoC 封裝了多個 CPU 晶片 (SCCL, Super CPU Cluster) 和 IO 晶片 (SICL, Super I/O Cluster),每個 SICL 都有一個 PCIe 根聯合體。

/sys/bus/event_source/devices/hisi_ptt<sicl_id>_<core_id>

調優

PTT 調優旨在監控和調整 PCIe 鏈路引數(事件)。目前,我們支援 2 類事件。事件的範圍涵蓋 PTT 裝置所屬的 PCIe 核心。

每個事件都表示為 $(PTT PMU dir)/tune 下的一個檔案,並且將使用一個簡單的 open/read/write/close 迴圈來調優事件。

$ 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 (事件 'filter' 的事件程式碼為 0x80001) 的 TLP 頭部,型別為已釋出的 TLP 請求,方向為入站,追蹤資料格式為 8DW。

1. 過濾器

要追蹤的 TLP 頭部可以透過根埠或端點的請求者 ID 進行過濾,它們位於 PTT 裝置的同一核心上。您可以透過指定 filter 引數來設定過濾器,這是啟動追蹤所必需的。引數值為 20 位。位 19 指示過濾器型別。1 表示根埠過濾器,0 表示請求者過濾器。位 [15:0] 指示過濾器值。根埠的值是核心埠 ID 的掩碼,該掩碼從其 PCI 插槽 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)。例如,具有 64 位地址的記憶體讀取的 TLP 頭部顯示在 PCIe r5.0 的圖 2-17 中;配置請求的頭部顯示在圖 2.20 中,等等。

此外,8DW 追蹤緩衝區條目包含時間戳,並可能包含 PASID TLP 字首的字首(參見 PCIe r5.0 的圖 6-20)。否則,此欄位將全部為 0。

DW0 的位 [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
[...]