1、 问题:某支持PCIE SRIOV功能的芯片X10在某CPU F10上,通过echo开出VF失败,现象是读VF的PCIE config空间都是FF。该芯片在X86 CPU上是能够正常开出SRIOV的。
2、 背景知识介绍:
a) PCIE EP设备config space寻址:bus+device+function,简称BDF结构。通过BDF定位要访问的EP。BDF一共16个bit的,分别是:
b) Bus是EP所在的总线号,本次问题中,X10的B:D:F=1:0:0
c) BDF中的device是EP在总线上的编号,这是从PCI继承过来的属性,PCI是广播型总线,可以连接多个设备。PCIE是点对点总线,只连接1个设备,device固定为0,所以bridge不会发出device != 0的type 0类型的访问,同理,EP设备也应该过滤device!= 0的type 0类型的访问。(当访问的bus不是bridge的下级总线,bridge使用type1请求,由下级bridge负责转发type1请求,在最终下级总线和请求的bus相等时,转换为type0请求,type1带device,bridge内部有虚拟的广播型总线,端口就是虚拟设备)
d) Function是EP内部的功能单元,3个bit,取值范围为0~7。也就是说一个EP设备,内部最多可以对PCIE总线呈现8个设备。
e) EP支持SRIOV,一个EP设备可以创建多个VF设备,但是在BDF寻址机制下,因为FUNCTION只有3个bit,一个EP只能对外呈现8个设备,所以不借助新的技术,一个EP的PF+VF总数不能大于8个,要大于8个设备,PCIE给出了两种方案:
i. ARI寻址,这是个可选功能。既然device对非bridge设备是无意义的,那么将device取消,将function的寻址从8扩大到256:
整个寻址仍然是16bit,BDF结构变为了BF结构。ARI需要bridge和EP同时启用,在启用ARI之后,bridge按照BF结构发出请求(device那5个bit可以不为0了,因为含义变为了function),EP按照BF结构解析请求。(对于EP来说,device那5个bit不为0的请求也可以接收了)。所以在ARI寻址下,一个EP的PF+VF的总数可以达到256个。同时因为我们习惯使用BDF来表示一个EP设备,即使ARI启用,我们仍然使用b:d:f格式表示一个设备,只是在硬件层面,已经对d已经做了重新的定义。
ii. 将VF放到其他总线。例如:X10在1:0:0,位于BUS1,在没有ARI的情况下只有8个function(或者即使有ARI,希望支持大于256个VF)。可以将VF放到下一个总线,例如总线2。但需要做一些修改:
1. Bridge对于不等于下级总线的请求,例如上图中,bridge0的下级总线是1,但是如果请求是发给总线2,。Bridge会发送type1的请求,因为请求的目的设备不在非直接下级总线,说明下级直连的设备是bridge,只有type1的请求才能被bridge转发。(同时,非ARI情况下,type1是可以device!=0的)
2. EP是不接收type1请求的,因为EP不是bridge,不处理type1请求, EP也不接收bus!=自身BUS的请求。
基于以上两个因素,SRIOV规范对支持SRIOV的EP提出了新的要求:
A Device receiving a Type 0 Configuration Request targeting an Enabled VF must process the Request normally. A Device receiving a Type 1 Configuration Request targeting an Enabled VF not located on the captured Bus Number must process the Request normally. A Device receiving a Type 1 Configuration Request targeting the Device's captured Bus Number must follow the rules for handling Unsupported.
总结就是,EP仍然不接受自身总线上的type1请求,但是要处理非自身总线上的type1请求。这个要求解决了VF位于非EP总线上的寻址问题。既然bridge能发出type1请求,那就让EP支持type1请求就OK了。这种情况下,VF理论上可以位于256个总线上的任何位置,具备了最大支持65535个VF的能力。
3、 本次问题中的关键点:
a) 排查发现CPU F10的pcie host bridge不支持ARI。一般X86 CPU都是支持的。
b) X10从设计上来看,只能工作在ARI寻址模式下的。因为X10的sriov VF参数offset=8,导致算出的第一个VF=1:1:0,其中device = 1,也就是非ARI模式下是无法访问到VF,说明X10在设计时就要求必须支持ARI,将device理解为function。
c) 在没有ARI功能的CPU上,又要支持大于8个VF,就只能将VF放到其他bus总线上。比如Intel XL710支持128个VF,他的VF计算参数offset是一个根据ARI的使能情况,动态可变的参数,:
ARI enable的时候,offset=0x10,计算出来的VF的bus不变。ARI disable的时候,offset=0x110,计算出来的bus的是PF所在bus的下一个bus。
d) 对于X10,按照PCIE规范,如果要支持32个VF(X10的规格),并同时适配有ARI和没有ARI的情况,要么offset固定为大于256的值,让VF落在其他总线,要么参考Intel的设计,offset动态可变,有ARI落本总线,没ARI落在其他总线。但不管哪个方案,在本问题中,因为CPU F10不支持ARI,所以VF只能落在其他总线。经排查X10芯片存在因为不接收type1的非本总线的请求,违背的SRIOV的规则,导致了本问题,经过芯片厂家修改估计,让X10能够接收type1的非总线请求,该问题解决。