我正在寻求一种机制来获取KVM中的访客物理地址(gPA)的访客虚拟地址(gVA)。我对KVM / linux内存管理知识非常有限,对这个领域是全新的,所以在我试着详细说明问题陈述时请耐心等待。
从linux-2.6开始,一种称为基于对象的反向映射(objrmap)的机制被用于在从内存交换页面之前使引用到页面帧的所有PTE无效。我理解anon_vma数据结构巧妙地收集相对于给定页面框架的所有内存区域描述符 - 并且基本上使用这样的事实:这些内存区域描述符具有指向包含引用页面框架的所有PTE的页面表的指针,以使它们无效。在本机设置(无虚拟化)中,可以通过执行一些简单的算法,轻松地使用anon_vma数据结构来查找进程线性地址空间中给定页面帧的虚拟地址:组合区域描述符(vm_area_struct)中的vm_start和页面描述符(结构页面)中的page->索引。
VA = anon_vma->vma_area_struct->vm_start + page->index
以下是了解Linux内核版本3的图片,描述了匿名页面的这种机制
我希望做类似的事情,在KVM中找到gVA,假设启用了二维寻呼(TDP)。但是,当我浏览KVM代码时,我看到KVM实现了一种反向映射方案,其中存储了指向所有引用GFN(访客帧号)的PTE的指针,而不是实现objrmap。由于它需要在x86(4kB,2MB,1GB)上支持3种不同的页面大小,因此它存储指向L1,L2和L3来宾PTE的指针。由于我无法获取内存区域描述符,我无法使用上述机制,其中我结合了vm_start和page_index。
我有以下问题。
gVA[47:39] = (Address of L4 PTE - guest CR3)/PTE size
gVA[38:30] = (Address of L3 PTE - L4 PTE PFN)/PTE size
gVA[29:21] = (Address of L2 PTE - L3 PTE PFN)/PTE size
gVA[20:12] = (Address of L1 PTE - L2 PTE PFN)/PTE size
这种做法是否正确?如果是这样,有没有办法获得L4客人PTE?
专家可以发表评论吗?我感谢任何帮助。感谢。