CPU共享内存地址空间的技术
目前市面上有三种设备共享内存地址空间的技术,UVA/SVM和SVA。使用SVA可以让软件设计更加简洁 ,软件不用去管理自己地址空间的iommu mapping,设备也可以访问更复杂的对象,比如链表,树等。 设计模型也更容易实现zero copy,设备也可获得足够的信息而自主地访问系统内存空间。
英伟达公司实现的是UVA的技术,GPU内部加入了MMU的功能模块,GPU的MMU模块使用的转换页表是CPU转换页表的镜像。
当GPU发现VA没有被记录在自己的MMU中之后,会通过PCIe总线从CPU的MMU页表中同步过来。反过来,CPU也可以从GPU内部同步页表项。
英特尔公司实现的是SVM技术,特点是通过PCI pasid绑定确定的CPU进程, 并且IOMMU访问CPU的MMU页表。当设备发现访问的地址不在设备的address translation cache (ATC) 中时,通过Adress translation service(ATS) 向IOMMU申请对应的转换页表。
SVM实现了设备访问虚拟地址空间的能力,并且设备不需要实现复杂的MMU功能,但有一定的限制如设备上的内存无法映射到CPU的内存地址空间。
ARM公司是SVA方案,CPU和外设间的连接的是支持cache一致性协议的总线。
DSA设备支持SVM方式
DSA设备支持的SVM模式在linux shared virtual address (SVA) 框架下进行了实现。DSA对SVM的支持是通过设备上的ATC,ATS的功能模块,PASID,page request service (PRS)来共同实现的。
PASID在PCI总线上的占用的是TLP 包头的部分,在PCI总线End-to-end数据包中使用20个bit为来传输PASID,这个值一般是iommu配置设备时指定的。具体格式可以参考PCI-spec6.0中关于PASID TLP的介绍。 PASID的分配和管理部分代码在kernel目录下的drivers/iommu/iommu-sva.c文件中。
PASID在IOMMU上面的支持也叫做scalable-mode,当scalable-mode使能的时候,会在传统的页表前加入PASID的上下文表项。
最新的VT-d spec中 Scalable Mode Address Translation 中可以看到每个设备有自己的PASID上下文,最后的PASID表会指向一级和二级页表。
ATS的实现是通过特别类型的TLP包来实现的,具体格式可以参考PCI-spec6.0第十章 Address translation service.
PRS的实现是通过特别类型的TLP包来实现的,具体格式可以参考PCI-spec6.0第十章 page request message相关的介绍。
DSA与主机共享地址空间
如果是host和DSA共享内存空间,ATC/ATS,PRS两者使能之后就可以实现。 PRS对应的是描述符flag中的block on fault比特位。
DSA与虚拟主机共享地址空间
如果是guest和DSA共享内存空间, 需要平台的scalable-mode是开启的,VMM需要为VM在IOMMU设置PASID。安排到虚机的DSA vDEV也需要支持ATS/PASID/PRS 这些功能。目前DSA vdev功能仍在社区检阅中。