据我了解,在没有硬件支持 guest 虚拟机托管物理地址转换的处理器上,KVM使用影子页表。

guest OS修改其页表时,将创建并更新影子页表。硬件中是否有用于修改页表的特殊说明(以x86为例)?除非有特殊说明,否则不会存在VMM的陷阱。 Linux内核不是通过软件维护的页表只是另一种数据结构吗?为什么需要特殊说明来进行更新?

谢谢!

最佳答案

我使用的不是KVM,而是使用其他VMM,所以我不知道KVM的详细信息,但是原理对于所有VMM都是相同的。它的工作方式是有两组页表。

除了用于页表基地址的特殊寄存器外,没有用于管理页表的特殊指令(以及其他寄存器中的一些随机位通常与配置处理器有关,但这通常是“一次性”设置)。页表只是用常规指令写入的内存的一部分-如果您确实想要[,除非您完全知道自己在做什么,否则它很可能会引起问题! ],但典型的操作是“mov”(存储)或“xchg”(交换)操作。

第一个页表是操作系统实际编写的页表。 VMM将其设置为只读存储器,因此,只要对其进行写操作,处理器就会发生页面故障。由于KVM使用处理器中的硬件虚拟化扩展(AMD处理器上的SVM或Intel处理器上的VMX),因此页面错误由VMM捕获(在本例中为KVM),在其中检查写入操作以查看其是否为“页面”。 -table write”,如果可以的话,它会转换为第二个影子页面表-这就是VMM使VM相信内存从0开始到1GB的方式,但实际上,我们占用了一堆页面到处都是,并集合了1GB的内存,这些内存似乎是一组连续的平坦页面。当然,由于VMM是“撒谎”到VM内的OS,所以我们不能让OS写入它的REAL页表,因为它不知道要在此处写入“TRUE”页表的值。 [但是,我们确实需要让操作系统拥有自己的页面表,以防它从页面表中读取,并且在操作系统实际不希望的时候完全感到困惑]。

处理器“实际CR3”由VMM设置,并指向影子页表。

VMM将捕获CR3(页表基地址)的写操作,以便它可以跟踪页表所在的位置(并跟踪要使用的“真实CR3”)。但是,VMM不需要了解CR3的读取,因此通常允许它们在VM中直接发生而不拦截它。

处理器中VMM扩展的全部要点是支持这种特殊指令的拦截,同时仍将VM中的大多数特权指令作为“常规”指令运行-例如,您不想跳入每次写入标志寄存器的VMM以启用/禁用中断等-使其在VM中发生,就好像它是真正的硬件一样。但是某些寄存器对于VMM可以控制至关重要。

显然,当页面表有硬件支持时,则存在两层页面表。一种将“0-1GB”转换为“分散在各处”,另一种是操作系统维护的实际页表。在这种情况下,无需拦截任何页表写入,页错误或任何CR3更新-操作系统可以在其允许的由基础页表映射的内存部分中执行所需的操作,并且如果VM走出允许的部分,则VMM会将其捕获为“VMM页表错误”。当然,这会使整个过程变得更有效率。

我希望这是有道理的。

关于linux - x86平台中的KVM影子页面表处理,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/14176904/

10-09 04:17