@[TOC](Linux drm内存管理(一) 为什么我们需要TTM和GEM?)
前言
目前Kernel中DRM中GPU的VRAM(GPU片上显存)的管理框架是有GEM和TTM,其中TTM早于GEM出现,GEM的出现是为了解决TTM复杂的使用方法,将大部分的VRAM管理实现逻辑交由厂商实现。
正文
如果你看了何总的GEM相关的博客,我这里额外补充一点我了解到的知识点,我们都知道了内核层的GEM指向或者说包含一片内存,应用层只能获取到GEM的handle,但是可以通过mmap获取到内核层GEM所指向的内存,从而实现CPU读写。
GPU可以使用自己的片上显存,同时也能使用CPU的内存。假设我们GEM指向的内存都在GPU的片上显存上,那我们多次创建和释放GEM,片上显存是如何实现管理的?比如第一个GEM指向的是GPU的0-16MB,第二个GEM指向的是16-32MB,第三个GEM指向的是CPU的某块内存。很明显GEM只能负责完成内存的映射,我们额外需要一个管理GEM的框架去管理显存的分配,或者说我们需要一个框架去统一GPU的内存寻址总线
思考
我看GEM和TTM还有AMD DRM的源码一直在思考一个问题,为什么要创建GEM\TTM框架去管理GPU的VRAM?
我们都知道CPU的内存 在Linux中通过伙伴系统进行管理,为什么GPU不能简单套用CPU的内存管理子系统,而要额外创建GEM和TTM框架来管理GPU的VRAM?
CPU 使用内存的方法:直接用alloc_pages向伙伴系统申请page,伙伴系统找一片空闲的内存返回,或者通过slab\slub\CMA\shmem等子系统间接申请page,申请成功后再对这些page进行读写。
GPU和CPU类似,想办法在显存中找一片空闲的区域,成功找到后再对这片区域读写。共同点都是申请一片内存区域,然后读写使用,为什么GPU要用GEM和TTM进行管理呢?
根本原因上面提到过,GPU的内存总类很多,寻址总线无法统一
GPU使用内存相比CPU有以下缺点
1.GPU的内存种类多
GPU有独显也有核显,核显借用CPU的RAM当作VRAM,独显有着自己的VRAM,当然也可以借用CPU的RAM当作VRAM,GPU的内存种类多,既能访问自己的显存,也能访问CPU的内存,GPU的内存总线没有统一,不同的bus访问方式甚至物理属性不同(解释下属性不同:如果Texture放RAM中,S3睡眠的时候内存是不断电的,如果Texture放VRAM中,S3睡眠数据全丢了),所以CPU内存管理框架无法运用在GPU上。
2.CPU与GPU之间带宽有限
内存直接挂在CPU的地址和数据总线上,CPU访问自己的内存很简单。
GPU一般是挂在CPU的外设总线上例如PCIE上,所以GPU的VRAM地址需要映射后访问。CPU和GPU不是直连,通讯带宽是有限的,我们当然可以通过将IO映射到总线上来,通过MMIO直接进行数据传输,但是访问会不断的触发外设的数据传输,而CPU和GPU的带宽肯定没有CPU和内存之间的带宽大,最好还是得借助老朋友DMA,去节省有限的带宽
3.GPU的内存使用方式与CPU不同
GPU的使用上,往往使用一片显存作为最小使用单位,例如一个Texture,Shader,而非单个字节做为最小单位。实际上对于应用层来说,我们不关心Texture被分配会在显存的哪个位置,也不关心Texture是如何分配的,所以我们建立Buffer Object(BO)的概念,作为GPU显存使用的最小单位。
综上,这就是GPU内存管理框架产生的原因,我们需要一套框架去管理BO的分配与释放,这套内存管理框架和核心思想:应用层并不需要在乎我们BO被分配在哪,但是内核层需要去处理GPU不同的bus,将bo放在合适的位置(例如VRAM或者是CPU的RAM)
TTM与GEM有什么不同
TTM是用GEM的实现内存管理框架(AMD提出),GEM一般被GPU厂商嵌入自己的数据结构,构造自己的内存管理框架。
BO主要的应用场景实现区别
1.BO需要从VRAM 转移到 RAM,或者是从RAM转移到VRAM。(TTM提供实现接口)
2.BO需要将指向的内存映射出来,供应用层CPU访问。(TTM/GEM提供实现接口)
所以说TTM要比GEM复杂。