0%

PCIe PRI分析

协议逻辑

PRI依赖ATS,带有PRI功能的设备,可以给IOMMU发page request,IOMMU为设备申请物理页,
并建立页表后,给设备发PRG response的消息。

PCIe协议里定义了PCIe设备和IOMMU之间的request/repsponse消息格式,并且定义了
PRI capability的格式,后者是软件可以读写的软硬件接口。

先看PRI capability的详细定义,这个cap只在PF里有:

  • cap head

    常规cap头。

  • status register

    response failure bit: 读到1表示收到一个failure的response。RW1C寄存器,写1清0。

    unexpected page request group index bit: 读到1表示收到一个非法PRI group index。
    RW1C寄存器,写1清。

    stopped bit: 只在enable clear的时候有效。这个是一个只读的指示位,为0时或者设备
    根本没有停,或者设备停了,但是链路上还有PRI request,当为1时,表示之前发出去的
    request都完成了(对应的response都回来了?)

    PRG response PASID required bit: 只读的指示位,PRG response带不带PASID,使能
    PASID的时候这个都应该是1?

  • control register

    enable bit: 控制是否可以发PRI request。从non-enable到enable的操作,清空status
    flags。enable和stopped同时处于clear,可能设备和IOMMU的连接通路上还有PRI request。

    reset bit: 只有在enable clear的时候有用,这个时候对reset写1,会clear page
    request credit counter和pending request state。

    估计上面这两个是硬件内部为了维护PRI request和response的具体实现, reset把这些
    东西清掉,使得设备回到复位状态,结合上面enable clear时只是disable PRI request
    的主动行为,并不保证清理链路上和设备里已经发出去的请求,这里的逻辑应该是这样。

  • outstanding page request cap

    定义page request的最大outstanding。page request的个数是资源,PRG index的个数
    也是资源,这里限定的是前者。

  • outstanding page request allocation

    用来配置实际使用的最大page request outstanding数。提供这个接口给软件的目的是
    要和IOMMU的处理能力做匹配,如果IOMMU的缺页处理能力比设备小,会造成PRI request
    失败。所以,这里对IOMMU就有了限制,可以直接想到的有: IOMMU处理PRI的队列最好独立,
    这样方便和设备的PRI outstanding能力做匹配; IOMMU需要考虑处理PRI请求队列溢出时,
    如何恢复; IOMMU的驱动需要考虑合理的匹配逻辑。

协议中定义的各种PRI相关的消息,这一部分软件无法直接感知。相关的硬件消息包括:

  • Page Request Message(PRM)

    设备发出的消息,一组消息可以组成一个group,group中的最后一个message有last标记
    去标记。

  • Stop Marker Message

    由设备发给IOMMU,告诉IOMMU,设备不再使用相关PASID了。

  • Page Request Group Response Message(PRGRM)

    IOMMU处理完一组PRM,对设备返回一个PRGRM,使用ID路由,携带pasid,group index,
    请求完成状态信息。注意这里是不带请求到的PA的。以group为单位返回状态信息,group
    里一个request failure,整个group就failure了。

    所以,PRI对IOMMU的诉求就是IOMMU要给软件提供下发PRGRM的接口,这个接口至少要有bdf,
    pasid,group index,PRM group处理返回值。

基于cap各个域段的分析,整体流程已经比较清楚了。唯一要注意的是PRGRM只返回处理
结果,需要接着再发ATS请求拿到PA,然后再发地址翻译过的请求。因为PRI翻译建立的页表
是可能变动的,如果收到PRGRM后直接用va访问可能会异常,所以接着发ATS拿到PA,依赖
ATS的同步机制保证发出的访问请求成功。

Linux驱动分析

目前Linux内核主线(Linux-5.14-rc4)已经支持了PCIe PRI的基本使能函数。相关函数在
drivers/pci/ats.c中,这些只是一些PCIe cap的操作函数。在业务中使用PRI功能的情况
还没有。