Linux drm内存管理(二) TTM内存管理基础概念

正文

通过之前的文章Linux drm内存管理(一) 浅谈TTM与GEM,为什么我们需要TTM和GEM?
  我们知道了TTM是在GEM的基础上实现的一套GPU内存管理框架,所以这篇文章介绍的侧重点是TTM是如何实现管理GPU内存的分配与释放,先了解TTM的思想,后续再结合代码。

基本概念

如果我们向TTM申请4M的内存,会发生那些操作,以这个为例,我们介绍TTM的概念。

总线(bus)

  之前的文章提到过,GPU的显存可以位于CPU的RAM中,也可以位于外设如PCIE的IO总线上挂的VRAM,TTM中根据BO所在位置不同,把bus分为IOMEM-bus,和MEM-bus,所以TTM需要判断将内存放置在IO总线上还是MEM总线上。

place

  以4k为单位划分Page,假设显存的大小为512M,共有128K个Page,申请显卡显存的时候,我们可以让TTM自动选择一块合适的区域,我们也可以单独指定范围,比如64K-68K Page的区域找一块空闲的显存,我们也可以指定placement,让TTM在一些指定范围内找空闲的显存,例如64K-68K,88K -92K, 100K-104K,如果64K-68K的显存已被申请使用,就查询88K -92K,依次类推,直到找到空闲的区域。

manager

  TTM的vram manager,负责纪录vram的申请释放,vram manager接收到了我们的请求,尝试从64K-68K寻址一块空闲4M内存,检查64K-68K中是否具有足够的空间,如果有,vram manager就创建resource,同时记录64K-68K这一区域中有4M的显存被使用了。

resource

  我们选择在64K-68K的VRAM范围中划分一块4M的显存,并且申请成功了,manager返回给我们resource,通过resource我们可以获取到这块显存的信息,如起始地址,大小等。
  但是就和CPU的写时复制一样,我们现在只申请拿到了resource,resource只标记了我们显存位于VRAM的64K-65K的区域,我们现在无法对这块区域进行读写。 (当应用层尝试对这块区域进行读写时,由于我们没有给resource分配实际的物理地址,所以会触发缺页中断,缺页中断中 我们将resource指向的IOMEM映射到总线上来,当然这是其中一种方法)

buffer object

  因为我们是以BO为单位操作/管理GPU显存的,所以resource申请后会attach到buffer object
现在我们拿到了BO了,并且BO在内核层为为我们从manager中申请到了64K-65K的显存,我们现在需要使用这一块显存,向这4M的显存中写值。

mmap

  因为TTM实际上是基于GEM的,所以接下来的操作和GEM类似,我们先mmap,在mmap中我们可以先不做映射,等到真正访问的时候触发缺页中断我们再映射,当然我们也可以在这个时候就开始将resource指向IOMEM映射到总线上来,此时应用层就可以对申请的GPU显存进行读写

上面介绍的显存位于显卡VRAM的方法,
如果显存位于CPU内存,需要GART table怎么办?

现在我们继续重复上面的步骤:

但是manager被选择为Gart Table manager,同样也需要从Gart Table 对应的寻找空间上寻找一块的地址,和VRAM的区别是多了一个ttm_tt的数据结构。

由于我们申请GART上显存的时候同样也没有分配实际的物理内存,在mmap的时候后 用户层触发缺页中断时,会申请CPU的物理内存,同时调用ttm_tt中的bind()函数,将物理内存地址写入GPU的GART table上,完成映射。

  总结一下,应用层的APP要向TTM框架的driver申请显存,首先driver确定需要显存的大小,其次根据传下来的一些flag选择合适的bus和place,接着向bus所在的manager申请显存resource,申请成功后将resource attach到bo,最后将bo的handle返回给应用层,如果申请的BO位于GART区域,在缺页中断的时候还会调用bind()将CPU的物理地址绑定在GPU的GART TABLE上。

你可能感兴趣的:(DRM内存管理,Linux设备驱动模型,DRM,Kernel,TTM,linux)