【58】PCIe错误处理机制是如何工作的

  向我最喜欢的对冲基金大佬-达里奥致敬,模仿《经济机器是如何运行的》写了一篇《PCIe错误机制是如何工作的》。文章主要介绍了主流的OS Native Model AER是怎么工作的。至于另外一种模式:Firmware First Model,其实没有啥好介绍的(主要是技术含量低,没啥好说的),可以参考《【19】怎么禁止PCIEAER的firmware first mode》。
公众号分成4篇介绍,背景更详细一些
https://mp.weixin.qq.com/s/hEK_b8l4VktwWeyqQNxF4A
https://mp.weixin.qq.com/s/Q2Nca9gLzunYLZMpMlG_Tw
https://mp.weixin.qq.com/s/NZT6CtKFyCRkTZ36r51fvA
https://mp.weixin.qq.com/s/2cWf-emOjWNzfnoWY2uQKA

1、 错误分类
在这里插入图片描述
  PCIe的错误可以分成两类:不可修复错误和可修复错误,其中不可修复错误又可以细分为致命和非致命两种。
  可修复错误由硬件修复不需要软件参与,并且修复行为不会导致任何信息的丢失。软件可以记录错误发生的频率。
  不可修复致命错误是链路或者硬件不可靠导致的,对于不可修复致命错误需要复位链路上的组件。不可修复致命错误,没有统一的修复方法,每家都有自己的处理方法。平台设计者需要根据硬件设计不同,PCIe器件承担的作用不同,业务流程不同进行不同的处理,原则上都需要复位链路上的组件。
  不可修复非致命错误通常是事务层不可靠但是链路满足要求导致的。
2、 错误上报
  PCIe Spec规定了3种错误上报机制:完成包状态,带内错误message,错误转发(例如data poisoning)
(1) 完成包状态
  只要完成包的状态不是SC,就代表对应的请求失败了。对于Non-posted的请求,只要completion包没有返回,请求就没有完成。
在这里插入图片描述
(2) 带内error message
  Error message起源于Root Port或者Root Port下面的设备,最终路由到对应的Root Port。
在这里插入图片描述
在这里插入图片描述
  如果RootPort支持AER,RC从message中提取RequesterID字段,并记录的Root port的Error Source Identification寄存器中,这个BDF号就是出错的设备。不过很多时候这个BDF是捕获不到的,或者出现多个错误,RC只能提取第一个错误的RequesterID。因此,需要driver遍历Root Port下的所有设备,检查哪些设备出现了错误。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
  如果Root Port支持AER,则收到error message(根据error code可以分为ERR_COR/ERR_NONFATAL/ERR_FATAL)或者Root port自己检查到对应错误时,会记录到Root Port的Root Error Status寄存器。
在这里插入图片描述
(3) 错误转发(data poisoning)
  出现Data poisoning时,TLP的EP比特会置1。
在这里插入图片描述
3、 Error message控制
  Error message从PCIe设备产生到路由到对应Root Por涉及一系列的控制寄存器和状态寄存器。
在这里插入图片描述
  Root Port下面的设备或Root Port本身发生PCIe错误想产生MSI中断话,需要关注哪些寄存器呢?
A. 整条链路上所有bridge的Bridge ctrl reg的SERR# bit
  如果该bit没有使能,则bridge不会往上游转发下游的设备上报的error message。如果是Root port本身产生的错误的则不需要关注该bit。
在这里插入图片描述
B. 整条链路上支持DPC的设备(DP和RP)是否使能了DPC
  如果使能了DPC trigger enable,下游设备发送的ERR_FATAL或ERR_NONFATAL的error message会被DPC拦截。

在这里插入图片描述
C. 整条链路上的所有PCIe设备的Device ctrl reg的对应bit是否使能
  Device ctrl reg的低4bit是一个比较大的控制开关,分布控制ERR_COR message、ERR_NONFATAL message、ERR_FATAL message和Unsupported
Request的发送。
在这里插入图片描述
D. Root port的Root error command reg对应bit是否为1
  如果Root error command reg对应bit为1,则Root port本身或者Root port收到下游设备上报错误时才会产生中断。
在这里插入图片描述
E. Root Port的Root ctrl reg对应bit是否清零
  如果Root ctrl reg对应bit没有清零,则会走左边的分支产生system error,对X86而言这是一条带外的pin。
在这里插入图片描述
F. 整个链路上的PCIe设备error mask reg是否置1
  如果error mask reg为1,则产生对应错误时,只会更新PCIe CAP的error status寄存器,不会产生error message。
在这里插入图片描述
在这里插入图片描述
G. Command寄存器的memory space enable bit和bus master enable bit是否为1,interrupt disable是否为1
  MSI中断本质上是一个memory write请求,Command寄存器的memory space enable bit和bus master enable bit负责MSI中断的产生和转发。
Interrupt disable是禁止INTx中断。由于,INTx优先级比MSI中断要高,该bit需要禁止。
在这里插入图片描述
H. Root Port的MSI enable是否为1
  Error message会路由到Root Port,如果想产生MSI中断,root port的MSI enable bit需要为1。
在这里插入图片描述
I. 一些特殊的reg
  由于每款芯片实现不一样,有些芯片还有一些特殊的reg控制使用MSI中断或者其他的中断。根据具体芯片设置,这里就不讨论了。
4、 Linux kernel的AER是怎么工作的
在这里插入图片描述
在这里插入图片描述
  Aer server和其他的PCIe server一样,都是注册给pci port bus driver。Port bus driver会调用aer_probe,aer_probe函数注册了中断服务函数和中断线程,然后调用aer_enable_rootport来使能中断。aer_enable_rootport其实就是清除error status reg,并且使能第3部分“Error message控制”提到的相关控制寄存器。
在这里插入图片描述
  中断服务函数aer_irq就是读取AER CAP中的status和source id 寄存器来确定是否产生了AER,收到的第一个错误message的id是多少,把status和id推到fifo中,然后就启动线程。
在这里插入图片描述
在这里插入图片描述
  线程aer_isr从Root Port 开始walk_bus遍历该root port下面的所有PCIe设备,读取设备aer status寄存器和aer mask寄存器,如果status对应bit为1且mask 对应bit为0,则加入struct aer_err_info *e_info的数据结构中等待处理。
  由于kernel需要为大多数使用者负责,追求通用性,导致aer的处理乏善可陈,就不在这里介绍了。
  AER处理方面,需要考虑产品可靠性要求不同、单板设计不同、芯片在系统中承担的角色等方面,通用性和可靠性不可兼得。Kernel要为所有硬件服务,因此选择了通用性。系统要想提高可靠性,就要适当牺牲通用性。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章