System paging process(MSDN翻译)
System paging process
大多数的分页操作都出现在系统分页进程(system paging process)上下文中。唯一的例外UpdateGpuVirtualAddress callback回调来更新的页表,UpdateGpuVIrtualAddress在一个特殊的companion上下文中并与渲染操作同步出现。
Microsoft DirectX graphics kernel使用系统分页进程来进行分页操作。例如:
- 在系统内存和GPU内存之间传输Allocation
- 给allocation填充pattern
- 更新页表
- 映射allocation到aperture段上
- Flush TLB(translation look-aside buffer)
分页进程拥有自己的GPU VA空间,GPU上下文和DMA Buffer(分页buffer)。并且也有自己的页表,这些页表被固定在物理内存上,只有在电源转换的时候才会被移出(evict)。
分页进程的VA空间拥有预定义的布局,并且在显卡初始化的时被初始化,也会在每次电源转换引起内存丢失时进行初始化。
DXGK会初始化足够的页表以及根页表中的项来覆盖1G的VA空间。碎片(scratch)区域用于转移和填充分页进程VA空间时临时映射allocation。如果allocation不能被碎片区域容纳,则转换操作将会被分块(in chunks)操作完成。
系统的根页表allocation为分页进程而创建。根页表内容在初始化之后不在改变(除了电源转换之后会Evict)。
系统分页进程的页表被分为两部分:
被创建的系统页表用于将映射碎片区域页表入系统分页进程VA。这样系统分页进程就可以修改碎片区域列表以及根据需要从碎片区域中映射或解映射内存。这些页表的内容也是在显卡初始化的时候被初始化,之后不会改变。碎片区域页表的表项用来将allocation映射入分页进程的VA空间。这些表项将会在初始化时置为无效状态以便在之后进行分页操作的时候使用。分页进程的页表通过 UpdatePageTable 函数在显卡初始化和电源产生事件时进行初始化。这些操作会将PageTableUpdateMode强制设置成CPU_VIRTUAL,会被CPU立即操作完成。
更新其他除了系统分页进程的页表项时PageTableUpdateMode的值是由KMD指定的。而这些更新操作都是在分页进程的上下文中完成的。
下面步骤说明了整个初始化过程:
1.根页表内存资源和低级页表内存资源创建时,这些页表一共覆盖了1G的地址空间。
2.这些页表的内存资源被提交到了内存段中。
3.KMD初始化页表项时会多次调用 UpdatePageTable 进行分页操作。
下面我们考虑在下面情况中,分页进程VA空间初始化的一个例子:
- 页面大小4KB
- 分页进程的VA空间是1GB
- 页表项大小为4字节
因此我们需要如下结构的2级翻译模式:
- 一个系统根页表
- 一个系统页表
- 255个碎片页表
接下来的图会说明页表会怎样基于根页表和页表在物理内存地址进行初始化。注意物理内存地址会以图示布局给出。一个页表覆盖了4MB的地址空间。所以这个系统页表覆盖了所有的的碎片区域页表。碎片区域页表从4MB VA处开始。将如你所见,VA范围从0到4095都将是无效的。