PCIe Chapter 14:從 TLP 標頭到 Flit 封包布局
TLP(Transaction Layer Packet,交易層封包)把要求、回覆與訊息送過 PCIe。讀取封包前,先確認 Link 使用 Non-Flit Mode(非 Flit 模式)或 Flit Mode(固定傳輸單元模式);兩者的 TLP(承載交易的封包)標頭布局不同。本章從這個分岔開始,把格式欄位接到位址、資料長度與有效 byte。
- OHC
- Orthogonal Header Content,Flit模式的擴充標頭內容
為什麼不能只背一張標頭圖?
在非 Flit 格式,先用 Figure 2-4 找 byte 0 的 Fmt/Type,再對 Table 2-2、Table 2-3。以 Memory Read 為例,Fmt 可表示 32-bit 或 64-bit 位址布局,要求不帶資料;Memory Write 則帶寫入資料。Type 也會影響路由,因此只看 Length 還不足以找到下一個封包。例如,另一筆 Non-Flit、32-bit 位址的 Memory Read 即使 Length=2,在沒有 Prefix 與 Digest 時,Request 本身仍只有 12 bytes Header,讀取資料由後續 Completion 返回。先確認這個 Type 是否帶資料,再使用 Length 計算封包大小。
換成 Flit 格式時,從 Figure 2-6 與 Table 2-5 重新開始。Type 不再只是舊格式的五個 bits;例如 Table 2-5 的 NOP 是 00h,而 32-bit 位址 Memory Read 是 03h。若沿用非 Flit 的解碼表,第一步就會讀錯。
找到基本標頭後,怎麼走到資料?
OHC(用來補充標頭資訊的擴充內容)由 Figure 2-6 的 OHC 欄位指出。接著讀 p.131 的出現順序,再用 Table 2-6 選擇適用的 A 類布局。例如有明確 Byte Enables 的 Memory Request,要沿 Table 2-6 找到 Figure 2-7 的 OHC-A1。後面的完整案例會把它接到實際的資料起點。不要固定假設所有 Flit 標頭都是相同長度。
- OHC
- Orthogonal Header Content,Flit模式的擴充標頭內容
TS 是 Trailer Size,用來指出尾部大小與用途;它與 Length 的資料長度分開計算。非 Flit 格式另有 Prefix(標頭前的擴充內容)與 TD(TLP Digest 存在標記)。判讀工具應先完成整個格式的大小計算,再移到後一包。
Header 前有 Prefix,應該從哪裡開始讀?
這裡先限定 Non-Flit Mode。TLP Prefix 是放在基本 Header 前的一個 DW(4 bytes),用來附帶特定用途的資訊。先在 byte 0 讀 Fmt[2:0]:100b 表示這個 DW 是 Prefix。接著看 Type[4]:0 是 Local Prefix,1 是 End-End Prefix。基本 Header 仍必須存在;只收到 Prefix 而沒有 Header,接收端須視為 Malformed TLP(格式錯誤的封包)。
- DW
- Double Word,4 bytes的資料單位
【模擬資料】以下資料為教學用途建立,不代表特定硬體或平台。假設一筆 Non-Flit TLP 依序有兩個 Prefix,後面才是 Memory Write Header 和資料;傳送端已依廠商方式啟用兩種自訂 Prefix,接收端也具備所需支援。下表只列每個 Prefix 的第一個 byte;其餘內容由廠商定義,不能從這個 byte 還原。
手機閱讀時,表格可以左右滑動。
| 封包順序 | byte 0 與拆解 | 查表後的類型 |
|---|---|---|
| 第一個 Prefix | 8Eh = Fmt 100b、Type[4] 0b、L[3:0] 1110b | Table 2-38:VendPrefixL0,廠商自訂 Local Prefix |
| 第二個 Prefix | 9Fh = Fmt 100b、Type[4] 1b、E[3:0] 1111b | Table 2-39:VendPrefixE1,廠商自訂 End-End Prefix |
| 後續內容 | 基本 Header → Payload → 若有則為 Digest | 仍需依實際 TLP 類型與欄位解讀 |
每個 Prefix 都占 4 bytes,所以本例的基本 Header 從 Prefix 開始位置後 8 bytes 才出現。若兩類 Prefix 同時存在,所有 Local Prefix 必須排在 End-End Prefix 前面;收到相反順序時,規格要求接收端視為 Malformed TLP。能找到 Header 並不表示後續交易一定合法或成功。
兩類 Prefix 的保護範圍也不同:End-End Prefix 隨 TLP 從來源送往目的端;Local Prefix 的大小、路由與 Flow Control 依其類型規定。當原本的 TLP 受 ECRC(End-to-End CRC,端到端完整性檢查)保護時,End-End Prefix 納入 ECRC 保護,Local Prefix 則不納入。這不代表沿途每個元件都一定支援或轉送該封包;End-End Prefix 的支援數量與出口阻擋仍需逐段確認。
最後回到兩張類型表與 §2.2.10.2.1、§2.2.10.4.1:廠商自訂的 Local 或 End-End Prefix 都必須先以廠商方式明確啟用,元件才可傳送。支援廠商自訂 Local Prefix 的元件還必須支援 3-bit Fmt,並將 Device Capabilities 2 的 Extended Fmt Field Supported 設為 1。對這兩類廠商自訂 Prefix,規格分別建議可配置成使用各自的任一編碼;這項建議不是必須實作的要求,也不表示兩端的 Local Prefix 編碼必須相同。
若接收端不支援收到的 Local Prefix 類型,且 Extended Fmt Field Supported=1,一般須將它視為 Malformed TLP,但其他規格明確另有規定時依該規定處理;此能力位為 0 時,行為由裝置決定。切換到 Flit Mode 後,必須改用該模式的 Type 與 Prefix 規則,不能直接套用上面的 byte 拆解。
PCI Express Base 6.0 §2.2.10.1–§2.2.10.2.1、Table 2-38(pp.199–200);§2.2.10.4、Table 2-39(pp.201–202);§2.2.10.4.1(p.203);§7.5.3.15、Figure 7-36/Table 7-33(pp.989、992)。文件頁與 PDF 頁相同。
Switch 支援 Prefix,為什麼要求仍過不了出口?
先區分接收能力、Prefix 數量與出口控制。§2.2.10.4 規定一筆 Non-Flit TLP 最多帶四個 End-End Prefix;支援 TLP Prefix 的接收端必須檢查這個上限,若發現超過,須視為 Malformed TLP。支援 End-End Prefix 的 Switch 必須能轉送最多四個,但每個出口是否允許轉送,還受自己的 Blocking 控制影響。
【模擬資料】以下資料為教學用途建立,不代表特定硬體或平台。某 Switch 收到一筆帶一個 End-End Prefix 的 Memory Read,已確認它是 Non-Flit Mode 的 Non-Posted Request,且 Switch 支援該 Prefix。路由選出 Downstream Port B 作為出口;此時 B 的 Device Control 2 中,End-End TLP Prefix Blocking bit 15 為 1。
讀 Figure 7-37/Table 7-34:出口 Blocking=1 代表禁止帶 End-End Prefix 的 TLP 經該出口送出。再回 §2.2.10.4:Switch 丟棄的是整筆 TLP,不是只移除 Prefix;TLP Prefix Blocked Error 記在出口 Port 的錯誤處理範圍。由於本例是 Non-Posted Request,出口 Port 還要回傳 Unsupported Request(UR)Completion。錯誤是否經上報機制到達 Root Port,仍需另查相關設定與紀錄。
若 B 的 Blocking=0,表示出口控制允許轉送,但仍要檢查目標與其餘路徑的支援情況。End-End Prefix 本身不改變 TLP 的路由方式;應先按原本的 Request 類型和位址找到出口,再檢查這個出口的設定。若是 Multicast,規格要求將 Prefix 複製到各副本,並在每個出口各自檢查阻擋。
目的 Function 的上限也要分開讀。除了 Root Port 的特別規則外,Function 收到超過其宣告上限的 End-End Prefix 數量時,須視為 Malformed TLP。Root Port 可以宣告小於硬體實際實作的上限;錯誤處理仍以宣告值為準。在不超過前述四個 Prefix 的前提下,對超過 Root Port 宣告上限的 Request,規格建議按 UR 處理,否則須視為 Malformed;Completion 則建議按 Unexpected Completion(UC)處理,否則須視為 Malformed。由入口 Port 收到的 TLP,錯誤歸屬入口;由內部接收、準備從出口送出的 TLP,錯誤歸屬出口。
接收端完全不支援 End-End Prefix 而收到帶有它的 TLP 時,規格也要求視為 Malformed。對 Upstream Port 的多 Function 情境,若其中一個 Function 設定了 End-End TLP Prefix Supported,所有 Function 對送給自己的不支援類型需分別將 Request 按 UR、Completion 按 UC 處理。軟體則應確保不把帶 Prefix 的 TLP 送往不支援的元件。
PCI Express Base 6.0 §2.2.10.4、Table 2-39,文件頁/PDF 頁 201–202;§7.5.3.16、Figure 7-37/Table 7-34,pp.994、997。Prefix 的基本格式見前節;Root Port 間的 P2P 轉送見下一節。
兩個 Root Port 都支援 Prefix,就能彼此轉送嗎?
不一定。前面的 End-End Prefix 可以隨 TLP 經過 PCIe fabric,但當 Peer-to-Peer(P2P,裝置彼此通訊)流量需要由 Root Complex 在兩個 Root Port 之間轉送時,§2.2.10.4.2 允許這項轉送能力依實作而異。Root Complex 若支援這類轉送,相關 Root Port 必須宣告支援;但即使兩個 Root Port 的支援位元都為 1,也不能只憑這兩個值確認該 Port 組合可轉送。
【模擬資料】以下資料為教學用途建立,不代表特定硬體或平台。Endpoint A 的 Non-Flit Memory Read 帶有一個 End-End Prefix,目標是另一個 Root Port 下方的 Endpoint B。兩端的 Root Port A、B 都回報 End-End TLP Prefix Supported=1;A 的 Max End-End TLP Prefixes 為 01b,B 為 00b。
先讀 Device Capabilities 2 的 Table 7-33:在支援位元為 1 的 Non-Flit 情境中,01b 表示支援一個 End-End Prefix,00b 表示支援四個。B 的 00b 不是零個。不同 Root Port 可以回報不同上限;若支援位元為 0,該上限欄位是 RsvdP(保留並應保留原值),不能套用上述解讀。
接著查 Root Complex 是否支援 A 到 B 的這組 P2P 路徑。若這筆 Request 必須經過不支援轉送 End-End Prefix 的 Root Port 組合,規格要求將 Request 當作 Unsupported Request(UR,不支援的要求)處理;對應情況下的 Completion 則按 Unexpected Completion(UC,非預期完成回覆)處理。這些錯誤由規格所稱的 sending Port 回報。沿途還要查出口阻擋與其他能力,才能評估具體路徑。
閱讀同一節時,再注意 Root Complex 與整合式 Endpoint(RCiEP)或主機軟體之間的方向:若 Root Port 支援轉送由主機軟體或 RCiEP 發起、帶有 End-End Prefix 的 TLP,或支援將入口收到的此類 TLP 轉送給 RCiEP,其 End-End TLP Prefix Supported 必須為 1。若 Root Complex 在 Root Ports 之間做 P2P 轉送時把一筆 TLP 拆成較小的 TLP,還必須把原本的 End-End Prefix 複製到每一筆小 TLP。
PCI Express Base 6.0 §2.2.10.4、§2.2.10.4.2,文件頁/PDF 頁 201–203;§7.5.3.15、Figure 7-36/Table 7-33,pp.989、992。範例的能力值與拓撲均為假設。
切換到 Flit Mode,End-End Prefix 要怎麼讀?
先從 Figure 2-6 的 OHC[4:0] 判斷是否有 OHC-E。OHC(Orthogonal Header Content,標頭擴充內容)位於 Header Base 後;若 A、B、C、E 同時存在,就依這個順序排列。§2.2.11 的 Figures 2-78、2-79、2-80 分別給出 OHC-E1、E2、E4,長度是 1、2、4 DW。它用來承載原本對應 End-End Prefix 類型 0011b–1111b 的內容;其他類型要查各自的 Flit Mode 規則。這個範圍不代表所有類型都可使用:Base 6.0 的 Table 2-39 將 0011b–1101b 列為 Reserved,本例使用的 1110b 與 1111b 是廠商自訂類型。
【模擬資料】以下資料為教學用途建立,不代表特定硬體或平台。假設使用兩種已明確啟用的廠商自訂 End-End 類型,資料內容分別為 12 34 56 與 AB CD EF,接收端也支援所需的 OHC-E2。以下比較的是兩種模式中相對應的資訊,省略基本 Header 和其他欄位。
手機閱讀時,表格可以左右滑動。
| 類型 | Non-Flit Prefix | Flit Mode 的 OHC-E 項目 |
|---|---|---|
| VendPrefixE0 | 9E 12 34 56 | 1E 12 34 56 |
| VendPrefixE1 | 9F AB CD EF | 1F AB CD EF |
先看每個 OHC-E DW 的 byte 0:高四位 0001b 代表有 Prefix 項目,低四位保留原本的 E[3:0];後三個 bytes 保留對應 Prefix 的 bytes 1–3。因此 9Eh 在這裡變成 1Eh,不能整個照搬。兩個項目依序放入 OHC-E2,佔 8 bytes;若沒有其他 OHC,Header 的 OHC[4:0] 可用 10000b 表示有 E2。
再讀 §2.2.11 的填入規則:項目從第一個 DW 開始依序放入,未使用的 DW 要標示為 No Entry。傳送端必須選用足夠容納內容的最小 OHC-E,避免不必要的 No Entry;例如只有一個項目時選 E1,三個項目則使用 E4 並將剩下的 DW 標為 No Entry。byte 0 高四位 0000b 是 No Entry,其餘位元保留;高四位 0010b–1111b 是 Reserved,接收端必須按 No Entry 處理,不能直接把它當成有效項目。
最後仍要確認目的端的 OHC-E 能力與完整路徑。Root Complex 在 Root Ports 之間轉送帶 OHC-E 的 P2P TLP 是選用能力,依實作而異;支援這項轉送的相關 Root Ports 必須宣告 End-End TLP Prefix Supported。這與前一節的 Non-Flit 路徑判斷相呼應,但欄位格式要依模式重新選擇。
PCI Express Base 6.0 §2.2.1.2、Figure 2-6(文件頁/PDF 頁 123、131);§2.2.10.4、Table 2-39(p.201);§2.2.11、Figures 2-78–2-80(pp.203–204);§7.5.3.15、Table 7-33(p.992)。案例中的廠商資料均為假設。
用同一個寫入需求,走完兩種格式
【模擬資料】以下資料為教學用途建立,不代表特定硬體或平台。兩段獨立 Trace 都由已配置的 Endpoint 03:00.0 發出 Memory Write,目標位址為 0x80001000。本例假設位址與路徑可用、允許裝置發起存取,且沒有 Prefix、IDE 或 TPH;保留欄位及其他未使用欄位填 0。兩段 Trace 的 Link 模式已由外部資訊確認,並已取得完整的邏輯 TLP。
- IDE
- Integrity and Data Encryption,完整性與資料加密
- TPH
- TLP Processing Hints,封包處理提示
兩筆資料負載相同,都是 A0 A1 A2 A3 B0 B1 B2 B3,Length=2 DW(每個 DW 是 4 bytes);但只要寫入中間四個 bytes。First DW BE=1100b,Last DW BE=0011b。Flit 案例從已重組的 TLP 開始,沒有把完整 FLIT 當作一筆 TLP。下列十六進位依圖中的 byte 0、byte 1 順序排列,每四個 bytes 換行;它不是 CPU 端的 DWORD 讀值表。
先讀 Non-Flit 的 20 bytes
40 00 00 02
03 00 00 3C
80 00 10 00
A0 A1 A2 A3
B0 B1 B2 B3
先用 Figure 2-4 讀第一個 byte:0x40 的 Fmt=010b、Type=00000b。查 Tables 2-2/2-3 的組合,得到帶資料、使用 3 DW Header 的 Memory Write。再用 Figure 2-5 讀 Length=2、TD=0;因此本例有 12 bytes Header、8 bytes Data Payload,沒有 Digest,合計 20 bytes。
接著換到 Figure 2-31。byte 4–5 的 03 00 是 Requester ID=0x0300,本例對應 03:00.0;byte 8–11 提供地址,得到 0x80001000。最後到 Figure 2-26/Table 2-10,讀 Header byte 7=0x3C:高四位是 Last DW BE=0011b,低四位是 First DW BE=1100b。Header 在 byte 11 結束,資料從 byte 12 開始。
再讀 Flit 格式的 24 bytes
40 01 00 02
03 00 00 00
80 00 10 00
00 00 00 3C
A0 A1 A2 A3
B0 B1 B2 B3
這次先讀 Figure 2-6,第一個 byte 的整個 0x40 都是 Type。查 Table 2-5 編號 64 的項目,得到 32-bit address Memory Write、Header Base=3 DW,Data Payload 由 Length 決定。這筆 Type 恰好與前例的第一個 byte 相同,不能用它單獨辨識 Link 模式。
byte 1 的 OHC=00001b 表示有 OHC-A;byte 2 的 TS=000b 表示沒有 Trailer,Length 仍為 2。先用 Figure 2-40 讀完 12 bytes Header Base,再依 Table 2-6 的 Memory Request 選到 OHC-A1。Figure 2-7 顯示這個擴充占 1 DW;其內部 byte 3 才是兩組 BE。換成整筆 TLP 的位置,就是 byte 12+3=byte 15,讀到 0x3C。
所以這筆的 Data Payload 從 byte 16 開始,總長度為 12+4+8=24 bytes。本例 OHC-A1 的 PV=0,沒有有效的 PASID;其餘不使用欄位為 0。OHC-A1 在這裡用來提供部分寫入所需的 BE,沒有增加資料負載的長度。
- PASID
- Process Address Space ID,程序位址空間識別碼
現在回到 §2.2.5.2 看這個擴充為何不能省:對這筆 2 DW Memory Request,若沒有 OHC-A1,接收端會把 First 與 Last DW BE 都視為 1111b。這會變成八個 bytes 全部啟用,已經改變原本只寫中間四個 bytes 的需求。OHC 是否存在,會直接影響接收端如何執行存取。
如果工具把第二段 Trace 當成 Non-Flit,就可能把 byte 7 的 0x00 誤讀成兩組 BE,並把 OHC 的 00 00 00 3C 當成資料起點,讓整段 payload 錯位四個 bytes。本例應先修正工具的解碼模式;這些假象不能直接當作線路上真的出現了錯誤封包。
每一步查哪張圖表?
PCI Express Base Specification Revision 6.0:Figure 2-4 Fields Present in All TLPs(PDF/印刷 p.119)→ Figure 2-5 Fields Present in All Non-Flit Mode TLP Headers、Table 2-2 Fmt[2:0] Field Values/Table 2-3 Fmt[2:0] and Type[4:0] Field Encodings(pp.120–121)→ Figure 2-31 Request Header Format for 32-bit Addressing of Memory(p.163)→ Figure 2-26/Table 2-10 Byte Enables Location and Correspondence(pp.150–151),完成 Non-Flit 判讀。Flit 改由 Figure 2-6 First DW of Header Base(p.122)→ Table 2-5 Flit Mode TLP Header Type Encodings 的編號 64(Type=40h)項目(p.125)→ §2.2.1.2 的 TS/OHC 規則、Table 2-6 OHC-A Included Fields for OHC-A1 through OHC-A5(pp.130–132)→ Figure 2-40 Flit Mode Mem32 Request(p.169)與 Figure 2-7 OHC-A1(p.132)。§2.2.5.2 Byte Enable Rules for Flit Mode(p.152)定義未帶 OHC-A1 時的預設 BE。上述 PDF 與印刷頁碼相同;閱讀順序是查詢路線,不代表硬體執行圖表的先後。
八個 payload bytes,為什麼只寫入四個?
沿用上面的兩筆模擬資料。§2.2.5.1 與 Table 2-10 把每個 BE bit 對應到資料 byte:First DW BE 的 bit 0 對應第一個 DW 的最低位址 byte;Last DW BE 的 bit 0 則對應最後一個 DW 的最低位址 byte。1100b 選到第一個 DW 的 +2、+3;0011b 選到最後一個 DW 的 +4、+5。
| 資料內的 offset | 對應位址 | Payload 內容 | 依本例 BE 執行的寫入 |
|---|---|---|---|
| +0、+1 | 0x80001000–0x80001001 | A0、A1 | 不寫入這兩個 bytes。 |
| +2、+3 | 0x80001002–0x80001003 | A2、A3 | 寫入 A2、A3。 |
| +4、+5 | 0x80001004–0x80001005 | B0、B1 | 寫入 B0、B1。 |
| +6、+7 | 0x80001006–0x80001007 | B2、B3 | 不寫入這兩個 bytes。 |
因此被選取的位址範圍是 0x80001002–0x80001005,共四個 bytes,但兩筆 TLP 的 Data Payload 都仍有八個 bytes。Length 維持 2 DW,接收端不會因為部分 bytes 沒被選中,就把它們從封包裡刪掉。本例也未跨越 4-KB 邊界,BE 選取的資料連續;其他長度、對齊或非連續組合,須再依 §2.2.5.1 檢查。
在本例的 Non-Flit 格式中,若改成 1 DW Request,Last DW BE 必須為 0000b;不能把本例的 0011b 直接沿用。這項規則接在 Figure 2-26 後,圖中的位置與周圍文字要一起讀。
TD 為 1,能確認接收端檢查過 ECRC 嗎?
只能先確認非 Flit 格式的 TLP 宣告帶有 Digest(尾端檢查欄位),還要檢查接收端能力與設定,才能判斷是否執行 ECRC(End-to-End CRC,端到端循環冗餘檢查)。沿用前面的 Non-Flit Memory Write:Header 為 12 bytes、Payload 為 8 bytes;若另設 TD=1,且沒有 Prefix,末尾的 Digest 再占 4 bytes,邏輯 TLP 共 24 bytes。這是作者依格式建立的模擬情境。
先查 Figure 2-5 的 TD 與 Length:Length 描述 Payload 大小,Digest 不計入其中。接著讀 §2.2.3:TD 與實際 TLP 長度若不相符,屬於 Malformed TLP,錯誤與接收 Port 關聯。若接收端不支援 ECRC 檢查,規則要求忽略 Digest;轉送 Multicast TLP 且出口啟用 MC_Overlay 的中間接收端有另列例外,須查 §6.14.5。支援檢查時,繼續查 §2.7.1 的使用條件。
不要把 TD=1 當成「檢查成功」的紀錄,也不要把 §2.2.3 的 Non-Flit TD 格式直接套到 Flit Mode。是否啟用與錯誤記錄,還需檢查實際接收元件及其 AER 設定。
- AER
- Advanced Error Reporting,進階錯誤回報
Base 6.0 §2.2.1.1、Figure 2-5(PDF/印刷 p.120);§2.2.2–§2.2.3 TLP Digest Rules - Non-Flit Mode Only(pp.142、144);§2.7.1 與 §6.14.5 提供後續條件。
同一個裝置的傳送與接收上限一定相同嗎?
不一定。MPS(Maximum Payload Size,TLP 資料負載大小上限)要分別從傳送 Function 與接收 Function 判斷。先查 Device Capabilities 的 Max_Payload_Size Supported、Rx_MPS_Fixed、Mixed_MPS_Supported,再查 Device Control 的 Max_Payload_Size 設定,最後回到 §2.2.2 判斷各欄位適用的條件。
傳送端先算 Tx_MPS_Limit:單 Function 裝置使用該 Function 的設定;ARI(Alternative Routing-ID Interpretation,替代的 Function 識別方式)裝置使用 Function 0 的設定。非 ARI 多 Function 裝置各 Function 設定一致時使用共同值;不一致時使用由實作選定的 Function 的值。軟體不宜在不了解實作時設定不同值。
若 Mixed_MPS_Supported=1,裝置有依目的地選擇 MPS 的實作機制,選定值可以高於或低於 Tx_MPS_Limit,但不得超過該 Function 宣告的 Supported 值;目標是 host memory 時仍使用 Tx_MPS_Limit。該機制如何為個別目的地選值,還要查實作資料。
接收端則先查 Rx_MPS_Fixed:為 1 時,Rx_MPS_Limit 使用該接收 Function 的 Supported 值;為 0 時,依 §2.2.2 的單 Function、ARI 或適用的非 ARI 多 Function 規則查設定。接收端必須檢查超過自身 Rx_MPS_Limit 的帶資料 TLP;若發現違規,按 Malformed TLP 處理,錯誤與接收 Port 關聯。
【模擬資料】以下資料為教學用途建立,不代表特定硬體或平台。一個 ARI 多 Function 裝置有 Function 0 與 Function 1;假設 Function 0 的 MPS 設定為 128 bytes、Function 1 為 256 bytes,Function 1 的 Supported 為 512 bytes,且 Rx_MPS_Fixed=1。Function 1 傳送至 host memory 時,Tx_MPS_Limit 使用 Function 0 的 128 bytes;Function 1 接收帶資料 TLP 時,Rx_MPS_Limit 則為 512 bytes。兩個結果分別約束不同方向,實際傳送仍須符合路徑與目標條件。
MPS 限制的是 TLP 攜帶的 Data Payload;Memory Read Request 本身不帶所要求的資料,其 Length 不是以 MPS 設定限制。讀取要求大小還要另查 Maximum Read Request Size 等適用規則。對支援 Flit Mode 的實作,Table 7-20 還要求 Supported 至少為 512 bytes,且 Rx_MPS_Fixed 必須為 1;不能把這個要求誤寫成每個 Non-Flit 裝置都相同。
從欄位接到傳送與接收規則
PCI Express Base Specification Revision 6.0:§2.2.2 TLPs with Data Payloads - Rules(PDF/印刷 pp.141–142);§7.5.3.3 Figure 7-24/Table 7-20 Device Capabilities Register(pp.955、958);§7.5.3.4 Figure 7-25/Table 7-21 Device Control Register(pp.959–960)。先在 Figure 找欄位,再讀 Table 中的能力和模式條件,最後依 §2.2.2 選用對應 Function 與方向。
看到不連續的 Byte Enable,就一定是錯誤嗎?
先沿用前面的 Memory Write,改變 Length、位址對齊與 BE,依 §2.2.5.1 比較。下表是模擬的 Non-Flit Mode Request;是否允許不連續,必須連同長度與對齊一起看。
手機閱讀時,可左右滑動表格查看完整內容。
| 條件 | First/Last DW BE | 規格判讀 |
|---|---|---|
| 1 DW Request | 1010b/0000b | 第一個 DW 可以不連續;1 DW 的 Last 必須為 0000b。 |
| 2 DW Memory Request,起點為 8-byte 對齊 | 1010b/0101b | 這種 QW 對齊的 2 DW Memory Request,兩個 BE 都允許不連續。 |
| 2 DW Memory Request,起點為 4-byte 但非 8-byte 對齊 | 1010b/0101b | 不符合此長度與對齊條件下的連續性規則。 |
Figure 2-26 只告訴我們 Non-Flit Mode 中欄位的位置;Table 2-10 把各 bit 對回資料 byte。再讀附近文字,才能判斷上述組合是否允許。Receiver 可以選擇檢查各項 BE 規則;若已實作的檢查發現違規,該 TLP 是 Malformed TLP。不能因沒有看到錯誤紀錄,就反推 BE 一定合法。
切換到 Flit Mode 時,先查 §2.2.5.2:Memory Request 若沒有 OHC-A1,First DW BE 預設視為 1111b;Length 至少 2 DW 時,Last DW BE 也視為 1111b。若需要其他 BE 值,須帶 OHC-A1。I/O 和 Configuration Request 分別有自己的 OHC 要求,不能把 Memory Request 的省略條件直接套用。
Base 6.0 §§2.2.5.1–2.2.5.2,Figure 2-26、Table 2-10,pp.149–152;QW 表示 8 bytes。
同一個 Header 位元組,什麼時候不再是 Byte Enable?
接續 Figure 2-26。Non-Flit Mode 的 Memory Read 或 Deferrable Memory Write(DMWr,可延後處理的記憶體寫入)若 TH=1,原本放 First/Last DW BE 的位置改用來承載 Steering Tag 的 ST[7:0]。此時不能把那個位元組直接拆成兩個 BE。
【模擬資料】一筆符合適用條件的 Memory Read,TH=1 且 Length=1 DW:First DW BE 的隱含值是 1111b、Last DW BE 是 0000b。若 Length 大於 1 DW,兩者的隱含值都是 1111b。規格只允許在可接受把要求視為所有請求 bytes 都啟用時設定 TH;帶讀取副作用的 Non-Prefetchable 區域還要留意 §2.2.5.1 的實作說明。
這個例子只處理 Non-Flit Mode 的欄位重用。若 Trace 是 Flit Mode,應回到該模式的 Header 與 OHC 規則,不要把 Figure 2-26 的位元組位置直接套用。
Base 6.0 §2.2.5.1、Figure 2-26,pp.149–150;TH/Steering Tag 的適用要求另讀 §2.2.7.1.1。
沒有啟用任何 Byte,為什麼 Read 還會收到資料?
【模擬資料】一筆 Non-Flit Mode Memory Read 的 Length=1 DW、First DW BE=0000b、Last DW BE=0000b。§2.2.5.1 規定,這類 Read 對應的 Completion 必須有 1 DW 長度及 1 DW Data Payload;其內容未指定,不能把回傳值當成讀到的裝置資料。
規格的 zero-length Read(零長度讀取)實作說明還提供一種用途:Requester 可用它確認先前 Posted Write 已完成到 PCIe 目的地。要讓這個用途在各情況下有效,Read 要指向與那些 Write 相同的裝置;規格建議可使用其中一筆 Write 的相同位址,且此作用只涵蓋與 Read 同一個 Traffic Class 的流量。這不等於確認應用資料已保存到非揮發媒體。
例如先發一筆 TC0 的 Posted Write,再對同一裝置發 TC0 的零長度 Read,接著觀察其正常 Completion;這時才有依規格判讀先前 Write 到達 PCIe 目的地的依據。若 Write 是 TC1,不能只靠這筆 TC0 Read 推論它已完成。也要保留完整路徑和 Attribute 等條件,不能只因送出 Read 就當作已收到回覆。
Base 6.0 §2.2.5.1,zero-length Write/Read 與實作說明,pp.151–152;Ordering 的詳細條件另讀 §2.4。
封包有回覆時,從哪裡接著讀?
先按 §2.2.9 確認這類要求需要 Completion(完成回覆)。Memory Read 的資料隨完成回覆返回;一般 Posted Memory Write 沒有對應的成功完成回覆。接下來到 Chapter 15,沿接收端的處理流程,確認合法性、能力與回覆結果。
版本與來源
本章以 PCI Express Base Specification Revision 6.0(6.0-1.0-PUB)為準,文件頁與 PDF 頁相同。案例的配置與讀值均為作者假設,並非實機測量。
完整來源定位
- §2.2.1.1; §2.2.1.2; pp.119,120,121,122,123; Figures 2-4, 2-5, 2-6; Tables 2-2, 2-3, 2-4, 2-5
- §2.2.1.2; pp.130,131,132; Figures 2-7; Tables 2-6
- §2.2.5.1; pp.149,150; Figures 2-26
- §2.2.9; pp.195


Comments