前面的文章提到過,PCI總線中定義兩個邊帶信號(PERR#和SERR#)來處理總線錯誤。其中PERR#主要對應的是普通數據奇偶校檢錯誤(Parity Error),而SERR#主要對應的是系統錯誤(System Error)。具體如下:
· 普通的數據奇偶校檢錯誤——通過PERR#報告
· 在多任務事務(Multi-task Transaction,又稱為Special Cycles)時的奇偶校檢錯誤——通過SERR#報告
· 地址和命令的奇偶校檢錯誤——通過SERR#報告
· 其他錯誤——通過SERR#報告
一個簡單的例子如下圖所示:
PCIe作為一種高速串行總線,取消了PCI總線中的這兩個邊帶信號,采用錯誤消息的方式來實現錯誤報告。但是,在軟件層面上,PCIe仍是兼容PCI總線的,具體后面會詳細描述。
在PCIe總線的錯誤報告機制中,有如下四個比較重要的概念:
· 錯誤檢測(Error Detection):指的是檢測某個錯誤是否存在的過程。
· 錯誤登記(Error Logging):指的是將相關寄存器(配置空間中的)的對應為置位,以等待軟件中的相關錯誤處理程序來處理該錯誤。
· 錯誤報告(Error Reporting):通知系統某個(或多個)錯誤發生了。在PCIe總線中,發生錯誤的設備會通過錯誤消息(Error Message)逐級將錯誤信息發送至Root,Root接收到錯誤消息后,會產生對應的中斷通知系統。
· 錯誤發送(Error Signaling):指的是通過發送錯誤消息(或者帶有UR,CA的Completion和Poisoned TLP)來傳遞錯誤信息的過程。
注:“帶有UR,CA的Completion”在前面的文章中介紹過,不熟悉的可以回顧一下。“Poisoned TLP”是PCIe總線錯誤報告機制中的Error Forwarding的方式,具體會在后面詳細介紹。
PCIe總線Spec定義了兩個錯誤報告等級。第一個為基本的(Baseline Capability),是所有PCIe設備都需要支持的功能。第二個是可選的,稱之為高級錯誤報告(Advanced Error Reporting Capability)。
在基本的錯誤報告機制中,有兩組相關的配置寄存器(配置空間中),分別為:
· 兼容PCI總線的寄存器(PCI-compatible Registers)
· PCIe總線中新增的寄存器(PCI Express Capability Registers)
高級錯誤報告機制(AER)中,又使用了一組專用的配置寄存器(配置空間中)。借助AER可以獲得更多的錯誤信息,有助於軟件定位錯誤源和分析錯誤原因。
PCIe總線的錯誤可以分為(Correctable Errors)和不可校正錯誤(Uncorrectable Errors)。其中,可校正錯誤可以自動地被硬件識別並被自動的校正或恢復。而不可校正錯誤又被分為非致命的(Non-Fatal)和致命的(Fatal)。非致命的錯誤一般有設備驅動軟件(Device Specific Software)直接處理,且鏈路(Link)可恢復,甚至鏈路上的數據有可能得到恢復(不丟失數據)。致命的錯誤只能由系統軟件(System Software)處理,且一般需要進行復位等操作,因此鏈路上的數據必然會丟失。
PCIe總線有三種錯誤報告方式,分別是:
1. Completions:通過Completion中的狀態位向Request返回錯誤信息
2. Poisoned Packet(又稱為錯誤傳遞,Error Forwarding):告知接收端當前TLP的Data Payload已經被破壞
3. Error Message(錯誤消息):向主機報告錯誤信息
錯誤消息的格式和對應的消息編碼如下所示:
為了兼容PCI總線的錯誤報告機制(使用PERR#和SERR#),PCIe設備會自動將CA、UR和Poisoned TLP轉換為對應的錯誤信息。具體這里就不詳細介紹了,有興趣的可以自行閱讀PCIe Spec的相關章節。
PCIe設備的配置空間中的狀態與控制寄存器如上圖所示,通過這些寄存器可以使能(或禁止)通過錯誤消息(Error Message)發送錯誤報告、查詢錯誤狀態信息,以及鏈路訓練和初始化狀態等。
前面的文章介紹過,默認的錯誤分類如下表所示:
這些錯誤類型可以通過設備控制寄存器(Device Control Register)中的相關位,進行使能或者禁止:
也可以通過設備狀態寄存器(Device Status Registers)相關位查詢錯誤狀態:
當然,當Root接收到錯誤消息后,怎么處理還要取決於Root Control Register的設置:
鏈路錯誤(Link Errors)一般發生在物理層與數據鏈路層通信的過程中。對於Downstream的設備,如果鏈路上發生了Fatal錯誤,此時,該設備並不能夠向Root報告錯誤。這種情況下,需要Upstream設備向Root來報告錯誤。為了消除鏈路錯誤,一般需要對鏈路進行重新訓練(Retrain)。如下圖所示,在鏈路控制寄存器中,可以通過往Retrain Link這一位寫1,來強制進行鏈路重訓練。
當發起重訓練請求后,軟件可以檢查鏈路狀態寄存器(Link Status Register)中的Link Training位,來確認鏈路訓練是否已經完成,如下圖所示。當該位為1時,表明鏈路訓練尚未完成(或者還沒有開始),如果鏈路訓練已經完成,硬件會自動將該位清零。
PCIe總線的錯誤登記與報告的流程圖如下圖所示: