KVM中的反向映射

Yas*_*the 5 linux memory memory-management kvm linux-kernel

我正在寻求一种在KVM中给定访客物理地址(gPA)的情况下获取访客虚拟地址(gVA)的机制。我对这一领域是完全陌生的,对KVM / linux内存管理的了解非常有限,因此在尝试阐述问题陈述时,请多多包涵。

从linux-2.6开始,在从内存中换出页面之前,使用了一种称为基于对象的反向映射(objrmap)的机制来使所有引用该页面框架的PTE无效。我了解anon_vma数据结构会聪明地收集相对于给定页面框架的所有内存区域描述符-并且一个基本的事实是,这些内存区域描述符具有指向包含所有引用该页面框架的PTE的页面表的指针,以使它们无效。在本机设置(无虚拟化)中,通过执行一些简单的算法,就可以轻松地使用anon_vma数据结构在进程线性地址空间内找到给定页面框架的虚拟地址:将区域描述符(vm_area_struct)中的vm_start与页面描述符(结构页面)中的page-> index。

VA = anon_vma->vma_area_struct->vm_start + page->index

这是理解Linux内核第3版中的图像,描述了匿名页面的这种机制

在此处输入图片说明

假设启用了二维分页(TDP),我希望在KVM中给定gPA的情况下执行类似的操作来找到gVA。但是,当我浏览KVM代码时,我看到KVM实现了反向映​​射方案,其中与实现objrmap相反,在其中存储了指向所有引用GFN(来宾帧编号)的PTE的指针。由于它需要在x86上支持3种不同的页面大小(4kB,2MB,1GB),因此它存储指向L1,L2和L3来宾PTE的指针。由于无法获取内存区域描述符,因此无法使用上述机制,将vm_start和page_index结合使用。

我有以下问题。

  • 如果只有我可以访问L4来宾PTE,则我打算执行以下算法来确定来宾虚拟地址:

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?

  • 还有其他简单的方法可以做到这一点,包括利用kvm_mmu_page中的字段吗?我似乎什么也没想。

专家们可以发表评论吗?我很乐意为您提供帮助。谢谢。