---
# System prepended metadata

title: 'PCI/PCIe(7): TLP processing hints(TPH)'
tags: [' System Software', I/O, PCIe]

---

# PCI/PCIe(7): TLP processing hints(TPH)

## Overview

TLP processing hints(TPH) 是由 [PCI-SIG](https://en.wikipedia.org/wiki/PCI-SIG) 所規範，一種可用於最佳化 PCIe 效能的可選機制。其允許 Requester 為記憶體空間的存取提供提示，告知其將要進行的記憶體存取之 pattern。則 Completer 可以根據提示更佳的管理系統資源。例如，Requester 可以指定資料應寫入哪個 cache，使得 host 更容易從 cache 中獲取資料，進而能提高效能並降低延遲。

TPH 旨在應用於以記憶體空間為目標的 transaction，適用於 device to host、device to deivce 和 host to device 的傳輸類型。在任何情況下，要支援 TPH，Requester、Completer 和所有中間的 Router 都必須支援相關的 TPH 功能。

對於 TPH 的詳細說明，可參考 PCIe 規格書 6.17 TLP Processing Hints (TPH)。


## Processing Hint(PH)

### TH

TLP header 的第一個 DWORD 中，TH bit 用於表示是否封包中是否存在 TPH 資訊。
* TH: 等於 1 表示存在 TPH

![image](https://hackmd.io/_uploads/rJgerosLZg.png)

### Processing Hint(PH)

對於 Completer 無法準確推斷存取方式，只有 Requester 了解即將發生的請求之 pattern 的狀況，通過 TPH 讓 Requester 向 Root Complex 提示預期如何使用資料，可以優化效能。需要此類提示的情況包括：
* DWHR：device 寫入後 host 很快就會讀取
* HWDR：device 將讀取 host 最近寫入的數據
* DWDW、DWDR、DRDW、DRDR：device 寫入/讀取後，device 很快又進行了後續讀取/寫入
* 雙向(Bi-Directional)： 資料結構由 host 和 device 共用且雙方具有同等讀取/寫入存取權限

這些資訊被編碼在 Processing Hint(PH) 欄位中。當 TH=1 時，PH 可以生效。


| PH[1:0] | Processing Hint               | Usage Model                                      |
|:------- |:----------------------------- |:------------------------------------------------ |
| 00      | Bi-directional data structure | Host 和 device 雙方頻繁對資料讀寫  |
| 01      | Requester                     | device 頻繁對資料讀寫(D\*D\*)                                           |
| 10      | Target                        | host 頻繁對資料讀寫(DWHR/HWDR)                                        |
| 11      | Target with Priority          | host 頻繁對資料讀寫 +所訪問資料具有高度 temporal locality |

PH 在 TLP header 中的位置如下表所示。

![image](https://hackmd.io/_uploads/B1xeM2j8Wg.png)


## Steering Tag(ST)

為了讓 Request 能連結到特定的處理資源（例如 host processor 或 cache），Requester 會需要在封包中嵌入一個特定於系統的值，用以指示系統（如 Root Complex）將資料存放在特定的 Cache Hierarchy 中，從而提升 Cache 利用率，最佳化數據存取效率。這個值稱為「Steering Tag」。

### Steering Tag Table

軟體將 Steering Tag 儲存在 Steering Tag table(後簡稱 ST 表)中，該表的位置有兩種可能性: 一種是位於 TPH Requester Extended Capability 結構中，另一種是結合 MSI-X 表使用。但一個 Function 只能二擇一，不能同時使用。當 ST 表與 MSI-X 表組合使用時，每個 MSI-X entry 的 Vector Control register 之兩個最高 bytes 用於儲存 Steering Tag 值。

ST 表的位置的取決於具體實作，並且可以透過軟體搜尋。
* 實現 MSI-X 的 Function 之 ST 表可以採用上述的任一方案
* 同時實現 MSI 和 MSI-X 的 Function，即便在 MSI-X disabled 的情況下，也可以將 ST 表與 MSI-X 表合併使用
 
每個 ST 表的 entry 使用 2 個 byte 表示，而 ST 表的大小在 TPH Requester Extended Capability 中指定。

### ST Table Location

TPH Requester Capability Regsiter(詳閱PCIe 7.9.13.2 節) 中的 「ST Table Location」欄位指示 Function 是否以及在何處實作了 ST 表。

![image](https://hackmd.io/_uploads/rkymK92LWl.png)
* ST Table Location 
    * 00: ST table 不存在
    * 01: ST table 在 TPH Requester Extended Capability
    * 10: ST table 在 MSI-X Table 

如果實現了 ST 表，軟體可以使用系統特定的 Steering tag 對其進行 program。

### ST Mode

而 TPH Requester Control Regsiter 中的 ST Mode Select 可以決定 ST 的使用方式:


| ST Mode Select[2:0] | ST Mode Name | Description |
| -------- | -------- | -------- |
| 000      | No ST Mode     | Steering Tags 必須使用全零值     |
| 001      | Interrupt Vector Mode     | 每個 Steering Tags 都由一個 MSI/MSI-X interrupt vector  number 表示。Function 所使用來的 ST 表 entry 中的 Steering Tag，必須可以透過有效的 MSI/MSI-X interrupt vector number 進行索引。     |
| 010      | Device Specific Mode     | 建議 Function 使用 ST 表 entry 中的 Steering Tag，但非必要。     |
| 其他      | Reserved     | 保留     |

![image](https://hackmd.io/_uploads/SJx6oc3UWg.png)

* 在 No ST Mode 下，Function 使用的 Steering Tag 只能是全零值，以允許在不使用 ST 的狀況下使用 PH
* 在 Interrupt Vector Mode 下，使用 MSI/MSI-X interrupt vector number 從 ST 表中選擇 Steering Tag
    * 對於啟用了 MSI 的 Function，其必須在 MSI Capability 中的 "Multiple Message Enable" 欄位指定的範圍內選擇 ST
    * 對於啟用了 MSI-X 的 Function，其必須在 MSI-X table 大小的範圍內選擇 ST
    * 如果 ST 表大小比啟用的 interrupt vector numbers 範圍還小，則允許該 Function 在某些 transaction 中不使用 TPH/使用 ST 為 0 的 TPH/使用特定 Function 的機制從 ST 表中選擇 ST
    * 如果 ST 表大小比啟用的 interrupt vector numbers 範圍還大，則 Function 將忽略超出 ST 表的 entry
* 在 Device Specific Mode 下，Steering Tag 的分配特定於裝置。Function 使用的 Steering Tag 數量可以與分配給其的 interrupt vector 數量不同，可以忽略 ST Table location 的欄位，甚至 request 中使用的 ST 也不需要來自規範的 ST table

能夠產生 TPH request 的 Function 必須支援 No ST Mode，其他模式則為可選。一次只能選擇一種 ST mode 運行，而這可透過對 ST mode 進行改寫來做選擇。

## TPH Capability

TPH Capability 是可選的 PCIe capability。每個能夠產生帶有 TPH 的 TLP request 的 Function 都必須實作 TPH Requester Extended Capability;而支援接收帶有 TPH 的 TLP 的 Completer 必須透過 Device Capabilities 2 register 指示 TPH Completer 的支援。

* TPH Requester Extended Capability
![image](https://hackmd.io/_uploads/rJ3u5UX_Zl.png)

* Device Capabilities 2 register
![image](https://hackmd.io/_uploads/BJWR9LmOWg.png)




## TPH Support on Linux

在 Linux kernel 中，TPH 的支援從 6.13 版本開始，需透過開啟 `CONFIG_PCIE_TPH` config 去啟用。

Linux kernel 會在 booting 期間識別 TPH 的支援，但裝置驅動程式需要主動啟用 TPH 以使用之。啟用後，驅動程式會使用提供的 API 取得目標記憶體的 Steering Tag，並將其寫入裝置的 ST table 中。

## Reference


- [Turning PCIe Hints into Cache Hits: Enabling Smart Data Cache Injection in Linux - Wei Huang](https://www.youtube.com/watch?v=SUzeEH5SlwY)
- [Linux Doc: TPH Support](https://docs.kernel.org/PCI/tph.html)
- [pcisig - TLP Processing Hints](https://pcisig.com/PCIExpress/ECN/Base/TLPProcessingHints)