Try   HackMD

PCI/PCIe(4): Transaction Layer

PCI Express Layering

PCIe 是一種序列匯流排(serial bus)。在 PCIe 協議上,所有操作都以封包(packet)的形式完成。舉例來說,假設 CPU 想要將一些資料寫入裝置。它將命令轉送到 PCIe Bridge,然後 PCIe bridge 會建立一個封包、之中寫入位址和資料、然後以序列方式轉送到目標。目標裝置收到封包後,再進行解析並執行之。

Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →

PCI Express® Base Specification Revision 5.0

PCIe 所連接兩端以封包的形式來溝通,以將資訊從傳輸端傳送到接收端。而 PCIe 是一個多層協定,由事務層(Transaction)、資料交換層(Data Link)和實體層(Physical)構成。傳輸時,每當封包經過下一層級後,會將原本的封包加上此層的封包所需的附加資訊。接收時則相反,封包由實體層步步拆解至事務層的封包,

Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →

PCI Express® Base Specification Revision 5.0

在本章節中,我們接針對事務層(Transaction Layer)進行更仔細的探討。

事務層(Transaction Layer)

事務層是協定的最上層,主要職責是 TLP(Transaction Layer Packet) 的組裝和拆卸。 TLP 用於例如讀取和寫入以及特定類型的事件。交易層還負責管理 TLP 的 credit-based flow control

每個封包都具有一個唯一的 id,使回應的封包能夠定位到正確的傳輸者。封包格式還支援不同形式的定址,根據事務類型可以分為 Memory、I/O、Configuration 和 Message 四種。其中 Message 方式主要目的是消除目前在實作中使用的各種 sideband 訊號,其支援把所有舊有(PCI)的 sideband 訊號轉變為 inband 訊號,例如中斷、電源管理的請求等。

封包格式

Overview

從系統軟體的角度,事務層(Transaction layer)的運作原理是我們理解 PCIe 重要的一環。在事務層,封包被接收。而封包可以有許多類型:比如讀寫記憶體、讀寫 I/O、表示完成訊息等。這一類封包在標準中稱為「事務層封包(Transaction Layer Packet, TLP)」。

PCIe 是 32 bits 的 bus,因此每 32 bits 的資料在 PCIe 上可稱為 double word(以下簡稱 DW)。每個 TLP 一般由 header (3-4 個 DW)和 data payload (0-1023 個 DW)組成。

為求容易理解,這裡暫時忽略可選的 TLP Prefix 和 TLP Digest。詳情請翻閱 PCIe Specification 的第二章 Transaction Layer Specification。

Header 的格式有許多種,但第一個 DW 會是相同的。Fmt 一欄位標示 header 的格式,比如 header 大小以及是否有 data payload 等。結合 Type 則描述了 TLP 對應的操作。詳情請見 PCI Express® Base Specification Revision 5.0Table 2-3 Fmt[2:0] and Type[4:0] Field Encodings

Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →

Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →

由於 PCIe 事務的類型複雜,要仔細闡述 PCIe 所支援的所有封包格式並不容易。這裡我們僅以舉例方式說明,過程會省略部分的特例與細節,只是嘗試讓讀者對 PCIe 傳輸的流程有基本的了解。如果需要完整的認識,請務必閱讀規格書。

Example: Write 32 bits data

假設 CPU 嘗試以 32 位元尋址方式,對 PCIe 周邊的實體位址 fdaff040 寫入 32 bits 的資料 0x12345678

在此案例中,現代平台常見的設計是 CPU 首先在自己的匯流排上執行寫入操作,而由於連接到 CPU 匯流排的記憶體控制器(memory controller) 直接連接到 PCIe 匯流排。因此,記憶體控制器能再藉由 Root Complex 產生一個記憶體寫入的封包,表明將資料寫入特定位址。封包經過 PCIe port 到達周邊裝置(中間可能有額外的網路,比如 switch 等)後,裝置對封包做解析並執行要求的寫入操作。

在封包部分。可由 4 個 DW 組成,具體內容如下所示。

Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →

這裡我們可以再觀察封包的更多細節:

  • FmtType 結合在一起,表示這是一個記憶體寫入請求
  • TD 為零,表示 TLP 資料上沒有 TLP Digest(額外的 CRC 資料)
  • Length 為 0x001,表示該 TLP 具有 1 個 DW payload
  • Request ID 欄位表示該封包的傳送者之 ID 為零,也就是 Root Complex
  • Tag 在此案例下是未使用的欄位。發送者可以在此處放置任何內容,而其他人都應忽略它。後面會再探討這有甚麼用途
  • 1st BE 欄位(1st Double-Word Byte Enable)可以用來選擇第一個 data DW 中的四個 bytes 之有效性。以本例來說,設定為 0xf 表示四個 bytes 都有效,應被寫入
  • Last BE 在 Length 為 1 時必須為零,因為第一個 DW 和最後一個 DW 是相同的
  • Address 表示資料寫入的起始位址
    • 0x3f6bfc10 << 2 == 0xfdaff040
  • Data DW0 表示所要寫入的資料 0x12345678

附帶一提,由於 PCIe 是使用 Big Endian,如果 CPU 是使用 Little Endian,則在其在軟體會需要寫入 0x78563412

Example: Read 32 bits data

假設 CPU 嘗試對 PCIe 周邊的實體位址 fdaff040 讀出 32 bits 的資料時又是如何呢? 在讀取操作上,這會比寫入稍微複雜一下,因為會涉及兩個封包:

  1. 從 Host 到周邊的 TLP,要求後者執行讀取操作
  2. 從周邊返回到 host 的 TLP,攜帶讀取到的資料內容

在 PCIe 術語中,我們有一個 Requester 和一個 Completer,在此案例中分別是 Host 和 PCIe 周邊。和上一個例子類似,CPU 在與記憶體控制器共享的匯流排上執行寫入操作,讓記憶體控制器藉 Root Complex 產生透過 PCIe bus 發送的 TLP。

在封包部分。這個讀取請求的封包由 3 個 DW 組成,內容如下。

Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →

大體上欄位和前述的寫操作相似。

  • FmtType 接合表示一個讀取請求
  • Request ID 欄位表示該封包的傳送者之 ID 為零,在讀取上此欄位至關重要,因為它告訴 Completer 應該將回應發送到哪裡
  • Tag 在讀取請求中很重要。當 Completer 回應時,它會將此值複製到 Completion TLP 中。這讓 Request 知道完成的封包是對應之前送出的哪個請求
  • Length 為 1 表示要讀取一個 DW
  • Address 表示從哪個位址讀取

關於 Tag 再額外說明。在 PCIe 上,單一裝置被允許發送多個請求,Requester 可以根據自身管理方式設定之,只要確保所有未完成請求的 Tag 都是唯一的即可。

當週邊收到 Read TLP 時,無論它是否能夠確實完成該請求,它都必須以某種 Completion TLP 做回應。若以成功讀取的結果為例,裝置從其內部讀取資料,然後將結果傳回給 Requester,封包會如下所示:

Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →

這個封包表示「告訴 Requester 0x0000,對於 0x0100 的請求中,其中 tag 標記為 0x0c 的一個之答案是 0x12345678。

  • FmtType 分別是 0x20xa,結合在一起表示這是一個帶有資料的 Complete TLP
  • Length 值為 0x001,表示該 TLP 具有 1 個 DW 的資料
    • 由於 TLP 的長度有限制,這個 Length 長度可能小於一開始 Reqeust 要求的 DW 數量,改以拆分為多個 Complete TLP 完成
  • Byte Count 所代表是包含目前的 Completion TLP 所剩餘需要傳輸的 byte 數量。在本例中,單個 TLP 就完成請求的情況中,其值為 4(bytes)
  • Lower Address 是 TLP 所讀取的起始位址之最低 7 個 bits。以本例來說 0x40(0xfdaff040 & 0x7f)。這個欄位在多個 Completion TLP 時非常有用
  • Completer ID 代表此封包的傳送者是 0x0100
  • Requester ID 表示封包的接收者 ID 為 0,也就是 Root Complex
  • Status 為 0 表示是一個成功的 Completion,其他值就用來不同類型的拒絕/失敗
  • BCM 欄位除了封包源自具有 PCI-X 的 bridge 的情況,始終是零
  • Data DW0 就是所得到的資料

Posted and Non-Posted operations

比較上述的讀寫案例,我們會發現一個明顯的差異: 讀操作無需等待額外的 Completion TLP,而寫操作需等待直到收到 Completion TLP。對於後者,這表示在收到 Completion TLP 之前,Requester 必須保留與 request 有關的資訊。甚至 CPU 開始讀取動作時,CPU 需持續等待直到成功讀取來自 PCI 裝置的資料。

PCI/PCIe 的術語上,這種發出請求即結束的操作稱為 Posted transaction,而由請求和完成組成的操作則是 non-Posted transaction。顯而易見,non-Posted transaction 容易造成更大的延遲。請參閱 PCIe 的規範手冊以得知關於 Posted/Non-Posted 的更多細節。

MPS

Max Payload size
ECRC

Rerfenece