GPU virtual address(MSDN 翻译)

GPU virtual address

GPU VA在DDI层次上被逻辑上分成4KB或64KB一页进行管理。这就允许GPUVA能引用系统内存(System Memory)或内存段(Memory Segment)。系统内存粒度为4KB,内存段可以为4KB,也可以为64KB。

视屏内存管理器(Video Memory Manager)支持多级虚拟地址翻译模式。这种模式采用了多级页表来翻译虚拟地址。页表层级从0级开始,第0级页表被指定为叶。地址翻译过程从根级页表(root level page table)。当页表一共有两级时,根页表能够改变大小来提供给进程可变的GPUVA地址空间大小。每一级页表都用DXGK_PAGE_TABLE_LEVEL_DESC结构体来描述,KMD负责在DxgkDdiQueryAdapterInfo的时候来填充该结构体。KMD还需要填充DXGK_GPUMMUCAPS 结构体来描述对GPUVA的支持情况。

每个进程拥有自己的GPUVA空间。在一个进程的图形处理上下文(a graphics context of a process)能够被执行之前,接口DxgkDdiSetRootPageTable 调用KMD来设置根页表的地址。

两级页表的情况下的VA翻译过程如下图所示

virtual address translation for the case of two page table levels is shown.

GPUVA所占的位数由 DXGK_GPUMMUCAPS::VirtualAddressBitCount来决定

低位部分(low bits)[0-11]表示了在目标页内的偏移。接下来由DXGK_PAGE_TABLE_LEVEL_DESC::PageTableIndexBitCount设置的位数代表了目标页在叶级页表(a leaf level page)中项的索引。

一个页面中可容纳项(entry)的数量为2^DXGK_PAGE_TABLE_LEVEL_DESC::PageTableIndexBitCount。而整个页表的大小为DXGK_PAGE_TABLE_LEVEL_DESC::PageTableSizeInBytes字节。

余下的位数表示了在根页表中叶页表项的索引。根页表在二级地址翻译模式下是可变长的,并且DxgkDdiGetRootPageTableSize这个DDI接口用来获取根页表的大小。

结构体DXGK_PTE用来在DDI中表示一个页表项。这个结构体表示了每一个项的有关信息,这些项被Microsoft DirectX graphics kernel管理。驱动使用这些信息去建立硬件指定的页表项(PS:这里的驱动不太清楚是指port端口驱动DXGK,还是mini port驱动KMD)。

Creation of page table allocations 创建页表Allocation

页表和隐式allocation一起被创建,创建时不存在UMD和KMD句柄。

为了分配页表,视频内存管理器从段(Segment)中分配了一个Allocation的大小DXGK_PAGE_TABLE_LEVEL_DESC::PageTableSizeInBytes。而段DXGK_PAGE_TABLE_LEVEL_DESC::PageTableSegmentId中指定(PS:这里指定的段ID是怎么对应的内存资源?根据上下文推测是叶页表项所指向的页)。创建之后,VMM使用分页操作函数UpdatePageTable 初始化这个页表中的每一个项为无效状态。在二级翻译模式(2-level translation scheme)中除了跟页表可以改变大小,其他页表均为固定大小。

二级翻译模式中,VMM支持改变根页表的大小。当要创建要给包含指定数量地址空间的根页表时,VMM调用DDI接口DxgkDdiGetRootPageTableSize用来确定实际需要的内存Allocation(PS:这里的Allocation可以理解为实际可用的内存资源)的大小。接着VMM在DXGK_PAGE_TABLE_LEVEL_DESC::PageTableSegmentId指定的段中分配出之前获得大小的Allocation作为根页表。在根页表创建之后,VMM使用分页操作函数UpdatePageTable 初始化根页表中的每一个项为无效状态。根页表能够根据进程对视频地址空间的增长和减少的需求量进行增长和缩减。一旦根页表被创建,VMM调用DDI接口DxgkDdiSetRootPageTable用来将这个页面和以后会在其中执行的不同上下文(context)进行关联。

在LDA(Linked Display Adapter)配置中,根页表被作为LinkMirrored资源创建。LinkMirrored拥有完全一样的内容,并且存在于在连接上的每个GPU中同样的物理地址上。次级页表(lower level page tables)作为LinkInstanced Allocation分配,反映了LinkInstanced Allocation的内容在不同GPU之间可能不同这个事实。所有GPU的次级页表的内容都是被独立的更新的。

Growing and shrinking a root page table 增长和缩减根页表

这一段描述只适用于两级页表的系统。当页表的级数大于两级时,每级页表的大小都是固定的并在VA能力(virtual addressing caps)中指定。

当UMD请求GPU VA时,VMM会增长对应进程的地址空间大小来响应这个请求。这个过程通过增长当前进程的根页表大小来实现,同样也要重新分配新的页表来映射新的地址空间。

为了增长根页表大小,VMM会创建一个新的根页表资源,并让它resident(PS:暂时没想到更好的翻译)。接着调用UpdatePageTable初始化所有的表项(PS:此函数里面应该也会进行拷贝内容,需要之后验证一下),初始化完毕后会将之前的根页表资源释放掉。 DxgkDdiGetRootPageTableSize函数用来得到新根页表的字节数。

为了缩小根页表,VMM创建了一个新的页表资源,让他resident。接着调用CopyRootPageTable拷贝旧根页表中部分内容到新的根页表中,随后销毁旧根页表资源。

在改变大小的操作完成之后,VMM会调用DDI DxgkDdiSetRootPageTable函数来让新的根页表和对应的Context关联起来.

Updating page table 更新页表

当surface在内存中移动时,VMM会通过DDI接口UpdatePageTable 更新代表surface新地址的页表内容。

Moving a page table 移动页表

当设备(PS:这里应该是指GPU引擎)在空闲或者挂起时,页表可能被VMM重定位(relocate)或者移出(evict)。当移动页表时,VMM会调用DDI接口UpdatePageTable更新高级别(higher level)的页表,这个高等级的页表引用着被移动页表的新地址。

而当根页表自己被移动位置时,VMM则是调用DDI接口 DxgkDdiSetRootPageTable通知对应的Context更新的页目录结构。

Physical page size 物理页大小

之前所提到了VMM所支持的两种页大小。系统内存(System Memory)永远被作4KB一页管理,而内存段(Memory Segment)可能被作4KB或64KB页来管理。采用哪种是由KMD来决定的。

当选择64KB来管理页面时,所有资源都被自动的按64KB来对齐,以及大小分配都是按64KB的整数倍来分配。

扩展所有的资源(allocation)都为64KB大小会对内存有很大的影响。因此UMD负责打包小的Allocation进入一个大一点的Allocation来避免浪费内存。

当映射GPUVA到一个64KB内存段(Memory Segment)页时,VMM将4KB页表项中16个表项映射到16个连续的4KB内存段页面。VA和PA都被确保共享同一段连续的64KB内存。(i.e. VA和PA的低16位地址确保一致)。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值