PCIe Chapter 12:錯誤證據、回報與隔離
先看本章的角色與路徑
作者依本章案例繪製的證據關係圖。訊息來源識別與實體故障原因需依其他證據繼續判讀。
AER(Advanced Error Reporting,進階錯誤回報)提供錯誤狀態、回報控制及相關紀錄。本章先走正常的錯誤回報路徑,再解釋遮罩與 DPC 隔離如何改變軟體看到的資訊。
- DPC
- Downstream Port Containment,下游連接埠錯誤隔離
前情提要:Chapter 5 的交易識別用來解讀有效的 Header Log;Chapter 7 的通知概念用來理解 Root 端如何把事件交給軟體。
規格路線:Figure 6-1 的分類 → Status/Mask/Severity → Figure 6-3 的回報路徑 → Root 紀錄 → 保存與清除 → DPC 分支。
- DPC
- Downstream Port Containment,下游連接埠錯誤隔離
PCIe 錯誤判讀需要串起偵測、回報、接收與隔離的證據。Status 記錄錯誤,不保證訊息送達;Source ID 識別回報者,不直接指出根本原因。本篇以 AER 與 DPC 的兩個獨立案例說明這些界線。
- AER
- Advanced Error Reporting,進階錯誤回報
先建立從 Function 到 Root 的證據關係
Correctable Error 可由協定恢復,但可能影響效能。Uncorrectable Error 影響功能,並依嚴重程度分為 Non-Fatal/Fatal;Non-Fatal 不能解成工作已成功,Fatal 也不是某顆晶片損壞的直接診斷。AER 提供比基本錯誤回報更細的狀態、遮罩、嚴重程度與 Log;沒有 AER 不等於完全沒有錯誤回報。
依序查看來源 Function 的 Status、偵測當時的 Mask/Severity/Device Control、有效 Header Log,再到 Root Error Status/Source ID 比對。若可能有隔離,另查 DPC Status。不同時間的設定不能自動套回事發時刻。依據:§6.2.1–§6.2.4(pp.669–679)、Figure 6-1(p.670)。
兩個 Status bit,只有一個未被遮罩
在 03:00.0 走訪 Extended Capability 清單,依 Figure 7-154 找到 AER ID=0x0001。本例 base=0x100,Version=2、Next=0;不能把 Base 6.0 的所有 Flit 欄位都當成這個 Function 的能力。假設先前紀錄已清、設定自事件前未變,沿途轉送條件已啟用。
| Register/位置 | 值 | 判讀 |
|---|---|---|
| Header/0x100 | 0x00020001 | AER,Version 2。 |
| Uncorrectable Status/0x104 | 0x00044000 | Completion Timeout bit 14、Malformed TLP bit 18。 |
| Mask/0x108 | 0x00040000 | 只遮罩上述 Malformed TLP。 |
| Severity/0x10C | 0x00040000 | Timeout 為 Non-Fatal;Malformed 為 Fatal。 |
| AER Capabilities and Control/0x118 | 0x0000100E | FEP=14、Timeout Header Log Capable=1。 |
| Device Control/0x78,16 bits | 0x2816 | Non-Fatal/Fatal Reporting Enable 均為 1。 |
- TLP
- Transaction Layer Packet,交易層封包
0x00044000 & ~0x00040000 = 0x00004000,本例只有 Timeout 未遮罩。Masked error 仍能設定 Status,但不為該次錯誤送出 Error Message,也不寫入 Header Log、TLP Prefix Log 或 FEP。Fatal Severity 不會越過 Mask。本例 Timeout 依 Severity 與 Device Control 產生 ERR_NONFATAL;這些值是設定後快照,不是預設值。
完整回報還有沿途 Bridge、Root primary interface 與中斷條件。依 Figure 6-3 查整條路徑;Unsupported Request/Advisory Non-Fatal 另有規則,不能普遍套用本例運算。
欄位與回報來源
Figures 7-154–7-157/Tables 7-134–7-137(pp.1112–1117);Figure 7-25/Table 7-21(pp.958–962);§6.2.3.2.2(p.673)、§6.2.6/Figure 6-3(pp.683–685)、§6.2.8.1(p.692)。
先確認 Log 有效,再解碼交易
FEP=14 且 Status bit 14=1,因此 FEP 有效。Completion Timeout Header Log Capable bit 12=1 才支持本例記下超時 Request;Multiple Header Recording bits 9、10=0,沒有 Flit/Prefix。本例用四 DWORD Log 容量,並只解讀三 DWORD Header。
| 位置 | DWORD 值 | 內容 |
|---|---|---|
| 0x11C | 0x00000040 | 3 DW Memory Read,Length=64 DW。 |
| 0x120 | 0x030013FF | Requester=0x0300、Tag=0x13、兩個 Byte Enable 均為 0xF。 |
| 0x124 | 0x40001000 | 起始位址。 |
| 0x128 | 不解讀 | 12-byte Header 的第四個 DWORD 未定義。 |
- DW
- Double Word,4 bytes的資料單位
Request 範圍為 0x40001000–0x400010FF,共 256 bytes;記錄的是未如期完成的 Request,不是超時的 Completion。Figure 7-161 的 DWORD 排列把 Header byte 0 放在 bits 31:24,不能再把上表反轉一次。Flit Log 須改查 Logged TLP was Flit Mode、Header Log Size、Logged TLP Size 與 Type/OHC。
- OHC
- Orthogonal Header Content,Flit模式的擴充標頭內容
Log 只能定位交易與等待結果,不能單獨指定 Endpoint、Completer、Link 或平台誰造成問題。它也不能分配給已 Mask、沒有本次 Log 的 Malformed TLP。
有效性與格式
§6.2.4.2(pp.679–680);Figures 7-160、7-161/Tables 7-140、7-141(pp.1121–1123);Memory Request 格式見 Chapter 5。
Root 的 Source ID 是第一個回報者
| Root AER base=0x100 | 值 | 意義 |
|---|---|---|
| Root Error Command/0x12C | 0x00000002 | Non-Fatal 中斷回報啟用。 |
| Root Error Status/0x130 | 0x00000024 | Uncorrectable Received 與 Non-Fatal Received。 |
| Error Source ID/0x134 | 0x03000000 | 高 16 bits 為 0x0300,即 03:00.0。 |
本例 Root 中斷向量編號為 0,且 primary interface 傳送條件已滿足。Source ID 表示回報 Timeout 的 Endpoint,不等於物理故障根因。第二個同類訊息會設 Multiple bit,但不取代第一個 Source ID。
Root Status 更新不受 Root Error Command/Root Control 控制,仍需要適用的 primary interface 傳送允許。要證明 CPU 收到中斷,還需向量與路由證據。依據:Figures 7-162–7-164/Tables 7-142–7-144(pp.1123–1127)。
清除前,先保存能互相比對的紀錄
作者建議先保存狀態、設定、FEP、有效 Log 與 Root/DPC 證據,並確認並行變化;多個 Register 的讀取不是自動原子快照。清除 FEP 指向的 Status 後,硬體可能換入下一筆 Log,所以先清再讀會破壞關聯。
啟用 Multiple Header Recording 且 FEP 有效時,規格建議依 FEP 逐筆處理,不清其他 Status;確定沒有 Header 的 masked error 有列明例外。PCI Status 與 AER Status 也不會互相連帶清除。依據:§6.2.4.2(pp.679–681,註腳 108)、§6.2.7.1(p.691)。
DPC 可能在 Root 收到原訊息之前隔離
換成另一事件:Switch Downstream Port 02:01.0 有 DPC base=0x300,不使用 RP Extensions。
| 欄位/位置 | 值 | 意義 |
|---|---|---|
| Header/0x300 | 0x0001001D | ID=0x001D、Version=1。 |
| Control/0x306,16 bits | 0x000A | Trigger Enable=10b,Interrupt Enable=1。 |
| Status/0x308,16 bits | 0x000B | Triggered、Reason=01b、Interrupt Status=1。 |
| Error Source ID/0x30A,16 bits | 0x0300 | 觸發的 ERR_NONFATAL 來自 03:00.0。 |
Enable=10b 可因本地未遮罩 Uncorrectable Error 或收到 ERR_NONFATAL/ERR_FATAL 觸發。此例 Reason=01b,Source ID 因而有效;若 Reason=00b,不能用 Source ID 判來源。觸發訊息在 Port 被丟棄,不再向 Root 轉送。本例只開 DPC 中斷、未開 DPC ERR_COR,所以不能要求 Root 出現前例的 0x24。
清掉通知後,Link 為什麼還沒有回來?
Figure 7-300 把 DPC Trigger Status 放在 bit 0,DPC Interrupt Status 放在 bit 3。兩者都能寫入 1 清除,但作用不同:bit 3 處理中斷狀態;bit 0 維持隔離,清除後才允許 LTSSM離開 Disabled,回到 Detect 嘗試建立 Link。
- LTSSM
- Link Training and Status State Machine,鏈結訓練與狀態機
【模擬資料】以下資料為教學用途建立,不代表特定硬體或平台。延續上方獨立的 DPC 事件:02:01.0 已收到來自 03:00.0 的 ERR_NONFATAL,DPC Status 讀為 0x000B。本例選擇先保存證據、只清中斷,再等待解除隔離的條件。到 Switch 的上游管理路徑仍可用,軟體經由這條路徑讀寫 Port 的設定空間;本次停用的是 02:01.0 到 03:00.0 的 Link。假設過程中沒有新的 DPC 事件,也沒有其他軟體同時寫入這個 Register。
| 動作與位置 | DPC Interrupt Status,bit 3 | DPC Trigger Status,bit 0 | 後續行為 |
|---|---|---|---|
| 讀取 0x308,得到 0x000B | 1 | 1 | 已記錄中斷與隔離事件;Reason=01b。 |
| 保存證據後,以 16-bit 寫入 0x0008 到 0x308 | 清為 0 | 維持 1 | 本例再讀為 0x0003,Port 仍在 DPC。 |
| 符合釋放條件後,以 16-bit 寫入 0x0001 到 0x308 | 本例維持 0 | 清為 0 | 回到 Detect 嘗試訓練;Reason 已無效,不指定整個 Register 的固定讀值。 |
這裡刻意拆成兩次寫入,讓通知與隔離的差別容易看清楚;規格沒有要求每套軟體都採這個拆法。真正必須遵守的是釋放條件。也因此,不能把讀出的 0x000B 原樣寫回,當成只清中斷的操作:那會同時對 bit 3 與 bit 0 寫 1,連隔離也一起釋放。
下圖的等待分支接到 §6.2.11:軟體必須先讀到 Link Status 的 Data Link Layer Link Active=0,才能釋放 DPC;若過早清除,結果為 undefined(規格未定義)。本例是 Switch Downstream Port,DPC RP Busy 不適用;支援 RP Extensions 的 Root Port 則還須等待該 bit 為 0。
- LTSSM
- Link Training and Status State Machine,鏈結訓練與狀態機
隔離期間又來一筆 Memory Read,誰回覆?
接著讀 §2.9.3 Transaction Layer Behavior During Downstream Port Containment。假設 Root Complex 送來一筆新的、格式合法的 Memory Read,原本應由 02:01.0 轉送到 03:00.0 的 BAR;它在 Port 已處於 DPC 時才提交給下游傳送路徑。這筆 Request 由 Port 丟棄,並由 Port 產生錯誤 Completion(交易回覆)。
- BAR
- Base Address Register,基底位址暫存器
為了知道回覆哪種錯誤,回到 Figure 7-299/Table 7-263:本例 DPC Control=0x000A,bit 2 的 DPC Completion Control=0,因此回覆 Completer Abort(CA,完成端中止);若該 bit=1,才改回 Unsupported Request(UR,不支援的要求)。此 Completion 的 Completer ID 是 Downstream Port 02:01.0,因為這次由它終止 Request;前面 DPC Error Source ID 的 03:00.0 則是觸發隔離訊息的回報者。
在這個情境中收到 CA,是 Port 依 DPC 規則產生的結果,無法據此宣稱 Endpoint 已接受或執行該次讀取。若換成隔離前就已送出的 Request,且 DPC 使 Completion 無法回來,本例沒有 Root Port Extensions 的代回覆機制,Requester 仍可能遇到 Completion Timeout。新的 Request 如何被終止,與舊 Request 是否已完成,要分別追蹤。
解除隔離後,還有哪些恢復工作?
Table 7-264 說明,清除 DPC Trigger Status 後,Port 離開 DPC,LTSSM 必須回 Detect。這只是重新嘗試訓練;接著還要觀察 Link 與 Data Link 恢復,並依 §6.6.1 遵守 Conventional Reset(一般重設)之後首次 Configuration Read 的適用時序,才能繼續恢復設定與驅動程式。等待條件連回 Chapter 9,不在這裡重複全部 Reset 流程。
解除隔離也會改變紀錄的判讀條件:DPC Trigger Status=0 後,DPC Trigger Reason 已不再有效,應使用先前保存的快照分析本次事件。規格允許在釋放要求已滿足後清除 Trigger Status,不必等所有相關錯誤 Status 都變成 0;因此,清空整片錯誤紀錄並不是恢復的必要前提。裝置如何重建工作、處理先前在途資料及恢復應用服務,則仍須裝置、驅動與平台的恢復程序。
從欄位、隔離中的交易,到釋放條件
依據 PCI Express Base Specification Revision 6.0。Figure 7-300 DPC Status Register/Table 7-264、§7.9.14.4(PDF/印刷 pp.1252–1253)定位 Trigger Status、Interrupt Status、Reason 有效條件與適用的 RP Busy。接 §6.2.11 Downstream Port Containment (DPC)(p.694),閱讀必須等 Link Active=0 才可釋放的要求;DPC 中斷條件見 §6.2.11.1 DPC Interrupts(p.697)。隔離期間 Request 的處理依 §2.9.3 Transaction Layer Behavior During Downstream Port Containment(p.262),再回 Figure 7-299 DPC Control Register/Table 7-263、§7.9.14.3(pp.1250–1251)查 DPC Completion Control。訊息來源欄位依 Figure 7-301/Table 7-265、§7.9.14.5 DPC Error Source ID Register(pp.1253–1254)。釋放後首次設定存取依 §6.6.1 Conventional Reset(pp.721–723)。上述 PDF 與印刷頁碼相同;本例的軟體處理順序是作者示範。
確認證據的限制
FEP=14,但 Status bit 14=0,還能用 Log 指認最新 Timeout 嗎?
不能,FEP 已無效。非零 Log 不能取代有效條件。依據:§6.2.4.2。
Status=0 能否證明從未發生錯誤?
不能;狀態可能已清除或重設,也須考慮偵測與實作條件。依據:§6.2.4.2、Table 7-135。


Comments