Press "Enter" to skip to content

Introduction to Shared Virtual Memory

Shared Virtual Addressing (SVA) allows the processor and device to use the same virtual addresses. SVA is what PCIe calls Shared Virtual Memory (SVM).

 

VT-d SVM: Extends root complex IOMMU to comprehend x86 page table formats

 

2. History

 

共享虚拟内存(SVM)技术最初是为了解决在GPU场景下,设备(GPU)和host(CPU)之间共享内存的。目的是在设备GPU和CPU之间可以直接传递指针(地址),为了让设备可以直接使用进程空间的地址,简化编程模型。我们知道通常host侧采用的地址是主机的虚拟地址(VA),而设备侧通常使用的是物理地址(PA)或IOVA。

 

如下图,传统内存访问的三个途径:

 

 

    1. CPU访存通过MMU(CPU的页表)将VA转为PA访问物理地址

 

    1. GPU访存通过GPU的页表访问物理地址

 

    1. PCIe设备直接使用物理地址PA访问

 

 

 

在引入了iommu(VT-d)后,如下图,PCIe设备也可以使用虚拟地址(IOVA)来访存了,也有设备自己对应的页表(iommu页表)完成IOVA到物理地址(PA)的映射。

 

这种情况下CPU进程和设备的内存通信一般采用如下流程:

 

 

    1. CPU进程分配一块内存,并采用系统调用syscall或ioctl请求内核准备接收操作

 

    1. 内核初始化设备的DMA操作,这里面有两种情况:一种是内核重新分配一块内核空间的内存,将其物理地址传递给设备进行DMA,另一种是如果应用程序将用户空间的内存pin住(这段内存的虚拟地址空间和物理地址空间不会发生变化)则可直接将用户空间的buffer地址传递给设备进行DMA

 

    1. 设备将数据DMA到内存,对应上面这里也有两种情况,如果是内核设置的内核buffer的地址,则设备会先将数据DMA到内核buffer,再由内核将数据由内核空间拷贝到用户空间的buffer(我们通常使用内核协议栈进行收发报文的应用程序就是这种),另一种如果用户空间直接将内存pin住,则设备直接将数据DMA到应用程序的buffer(我们采用DPDK收发报文就是这种)

 

 

 

3. 引入SVM后的变化

 

下面我们看引入SVM后的效果,最大的区别是设备访问地址在经过iommu的DMAR转换时会参考引用CPU的mmu页表,在地址缺页时同样会产生缺页中断。为什幺要这样设计呢?因为要想设备直接使用进程空间的虚拟地址可能采用的有两种方法。一种是把整个进程地址空间全部pin住,但这点一般是不现实的,除非类似DPDK应用程序全部采用静态内存,否则如果进程动态分配一个内存,那幺这个地址设备是不感知的。另一种方法就是采用动态映射,就像进程访问虚拟地址一样,mmu发现缺页就会动态映射,所以从设备发来的地址请求也会经过CPU缺页处理,并将映射关系同步到iommu的页表中。

 

有了以上的流程,CPU和设备的内存交互流程就变成了如下图所示。主要是第三步的变化,设备直接将数据DMA到进程空间的地址,并且不需要进程pin内存,而是通过page fault触发缺页处理进行映射。

 

4. 支持SVM的条件

 

那幺支持SVM需要软硬件具备什幺条件呢。首先是设备角度:

 

 

    1. 要支持PASID,因为一个设备会被多个进程访问,对应多个设备DMAR页表,需要通过PASID来区分采用哪个页表

 

    1. 支持dma page fault处理,当访问的虚拟地址引发缺页时能够等待或重试

 

 

从驱动角度来说,

 

 

    1. 操作设备的API需要通过PASID来区分不同进程

 

 

 

参考资料:

 

Shared Virtual Addressing (SVA) with ENQCMD
SVM on Intel Graphics
Shared Virtual Addressing in KVM kvm forum 2018
Shared Virtual Addressing in KVM

Be First to Comment

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注