转载:(13 封私信 / 81 条消息) PCIe协议学习-浅谈SR-IOV - 知乎
1:背景和概述:
AR-IOV,全称叫single root I/O virtualization and sharing,顾名思义,这是一种虚拟化技术,目的是让多个终端或者叫做system image(SI)共享PCI设备资源,提高硬件资源得利用率。
一般的虚拟化系统架构如下图所示,多个SI可以共享某个PCI设备,virtualization intermediary(VI)负责管理其下面的硬件资源 ,同时只把每一个SI自己可以访问的资源呈现给他们,因此可以说,每个SI看到的系统(system)是一个"虚拟化"的系统。

这个架构的问题就是所有的IO命令和数据都需要VI处理分发,当多个SI都和PCIe设备有大量IO交互时,要保持系统性能,对VI的硬件性能要求会非常高,即所谓的"significant platform resource overhead"。
SR-IOV的引入,就是为了减少这种resource overheads,具体方法其实也就是在不增加太多resource overheads的前提下,尽量卸载VI的数据流处理功能(包括DMA,memory space access,interrupt process等),另外就是SR-IOV可以兼容其他的IO virtualization technologies,比如address translation service(ATS)等,这里不做展开,SR-IOV的系统架构一般如下图所示。

这个系统增加了以下这些功能模块:
1:SR-PCIM
single root PCI manager,负责SR-IOV相关配置,管理physical functions(PF)和virtual functions(VF),同时处理相关的error events和设备的一些功能管理,如power management和hot-plug service等。
2:TA
optional translation agent,负责做上下游的PCIe transaction的地址转译,TA可能还会包含一个address translation cache(ATC),作为查表缓存来加快转译速度。
3:ATPT
optional address translation and protection table,TA通过查询ATPT完成PCIe transaction的地址转译。
4:ATC
optional address transaction cache,前面提到,ATC可能在TA中,同时设备中也可以有一个ATC模块,这主要时考虑兼容ATS,已经完成地址转译的PCIe function,可以bypass 系统中的ATC,以提高性能。
5:PF
physical function,就是支持SR-IOV特性的PCIe function,同时可以被SR-PCIM,VI和SI等访问。
6:VF
virtual function,一个可以被SI直接访问的轻量级(Light-weight)的PCIe function,可以认为的PF的子集,也是SI进行数据操作的最终容器(或者说对象),但是SI无法配置VF。一个VF可以先被分配给一个SI,然后reset,并被分配给两一个SI,但任一时刻只能有一个SI具有访问权限,一个VF也可以先分配给一个PF,再分配给另一个PF。
2:ARI
在进一步讨论SR-IOV前先介绍ARI,一般的,routing ID,requester ID和completer ID都是8bit bus number,5 bit device number,3-bit funciton number组成,在ARI模式下,device number 不再使用,由8-bit bus number + 8bit funciton number组成,因此,ARI设备可以支持到256个functions(不考虑AR-IOV)。
软件在枚举时如果发现一个设备支持ARI(存在ARI capability register寄存器),则需要使能和ARI设备对接的downstream port中的ARI forwarding enable bit in the device control2 register。使能之后,这个DP可以正常将type1 configuration rquest转换成type0 configuration request(原先的type1到type0的转换,要求device number域段为0)。
ARI extended capability:

ARI capability register(offset 04h)


如果设备支持MFVC function groups(multi-function virtual channel function groups,bit 0),不同的function可以分配到不同的function group(最大8个function groups),Device将基于function groups进行调度,每个function group内的进一步调度方式时implementation specific的。
ARI Control register(offset 06h):



3:PCIe设备中的PF和VF
日常工作中,我们接触EP或者说PCIe设备比较多,所以本文也会重点讨论一下PCIe设备相关的SR-IOV功能,一个支持SR-IOV的PCIe设备(多个PF,每个PF还包含0个或者多个VF)如下图所示:

几点说明如下:
1:每个PF可以有0个VF,多个PFs之间的VFs数量可以不同
2:ARI(Aliternative routing indentifier)extended capability寄存器定义了设备funciton group的配置,比如arbitration和下一个funciton的寄存器offset等。
3:支持ARI的设备最多支持256个PFs,不同的function number需要在256范围内,但是不需要连续分配。
4:一个SR-IOV设备可以占用多个bus number,每一个VF都可以关联一个在设备bus number range内的bus number。
5:每个设备都必须有function0,funciton0可以是一个PF(支持SR-IOV,可以包含多个VFs)
不同function的arb的问题,这里不展开讨论,下面主要讲一下设备AR-IOV的配置和使用。
4:PCIe设备SR-IOV配置
SR-IOV extended capability: 
每一个支持AR-IOV的PF都需要一个SR-IOV extended capability寄存器。
SR-IOV capability register如下图所示:



SR-IOV control register如下图所示:

SR-IOV Control Register(offset 08h)的bit 0表示VF Enable,如果clear了bit 0,这个PF的所有VFs都会被disabled。Bit 1表示VF Migration Enable,表示是否支持VF migration。Bit 3是VF MSE(memory space enable),表示能否访问该PF下VFs的memory space。Bit 4用于指示上游设备是否enable了ARI。
SR-IOV status register如下图所示:


pcie gen6 好像已经不再使用。
回到SR-IOV capability register 中继续来看:
**TotalVFs:**表明这个PF可以支持的最大VFs数量,
**InitialVFs:**表明这个PF初始的VFs数量,
**NumVFs:**表示这个PF当前enabled的VFs的数量,
**function dependency link:**表示不同PF之间是否有依赖,如果没有,这个寄存器需要(由软件)填成PF自身的fucntion number,如果PF之间有一个dependency list,且PFa为其中一个,则PFa的fucntion dependency link的值应该为dependency list中下一个PF(比如PFb),dependency list中最后一个PF的值为list中的第一个PF。dependency对PCIe配置有如下约束:
1)同一个dependency list中的PF,initialVFs和TotalVFs的值必须相等;
2)软件需要给同一个dependency list中的PF配置相同的NumberVFs和VF enable;
3)同一个dependency list中的PF必须分配给相同的SIs,VFs也必须要分配给相同的SIs;
First VF offset(offset 14h):PF的第一个VF routing ID offset;
VF Stride(offset 16h):表示该PF中不同VFs之间的routing ID offset;
VF device ID (offset 1Ah):表示每个VF呈现给的device ID;
supported page sizes(offset 1ch):表示该PF可以支持的page size(4KB*2n if bit n is set),协议要求PFs至少要支持4/8/64/256/KB,1MB和4MB page size。
system page size(offset 20h),表示系统最终使用的page size。
VF BAR0-VF BAR5,VFs 的base address register,用法和一般的PCI BARs一样(系统软件先写全1,然后读回来确定每个BAR空间大小,最后系统软件可以给每个BAR分配基地址),所有BAR的空间大小加起来就是这个PF中VFs的空间大小(所有VF大小是相同的),第一个有效的VF BAR中的地址就是这个PF的第一个VF的基地址,其他VFs的基地址需要基于第一个VF的基地址的每个VF的空间大小换算:


根据First VF Offset和VF Stride,可以确定每个VF的routing ID(RID):

所有的VFs和PFs都有distinct routing IDs,假设设备对应的bus number是N,那么最终的routing ID是256*N + RID。