8

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

当客户操作系统修改其页表时,会构建和更新影子页表。硬件中是否有修改页表的特殊说明(我们以x86为例)?除非有特殊说明,否则 VMM 不会有陷阱。Linux内核在软件中维护的页表不就是另一种数据结构吗?为什么需要特殊说明来更新它?

谢谢!

4

1 回答 1

15

我使用除 KVM 之外的另一个 VMM,所以我不知道 KVM 的详细信息,但所有 VMM 的原理都是相同的。它的工作方式是有两组页表。

除了页表基地址的特殊寄存器[以及其他寄存器中的一些随机位与一般配置处理器有关,但这通常是“一次性”设置]之外,没有管理页表的特殊指令。页表只是用常规指令写入的内存位——如果你真的想要,你可以做加法、减法和或乘法等[除非你绝对知道你在做什么,否则它很可能会导致问题! ],但典型的操作符是“mov”(存储)或“xchg”(交换)操作。

第一个页表是操作系统实际编写的页表。VMM 将其设置为只读内存,因此每当对其进行写入时,处理器就会出现页面错误。由于 KVM 在处理器中使用硬件虚拟化扩展(AMD 处理器上的 SVM 或 Intel 处理器上的 VMX),页面错误由 VMM(在本例中为 KVM)捕获,其中检查写入操作以查看它是否是“页面-table write”,如果是这样,它会被转换为第二个影子页表——这就是 VMM 使 VM 相信内存从 0 开始并达到 1GB 的方式,但实际上我们已经占用了一堆页面到处都是,并把 1GB 的内存放在一起,这些内存看起来是一个平坦的、连续的页面集。当然,由于 VMM 对 VM 内部的操作系统“撒谎”,我们不能让操作系统编写它的真实页表,因为它不知道要写在那里的“真实”页表值。[但是我们确实需要让操作系统拥有自己的页表,以防它从页表中读取并且在它不是操作系统实际期望的情况下完全混淆]。

处理器“真正的 CR3”由 VMM 设置,并指向影子页表。

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

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

显然,当页表有硬件支持时,就会有两层页表。一个将“0-1GB”翻译成“分散在各处”,另一个是操作系统维护的实际页表。在这种情况下,不需要拦截任何页表写入、页错误或任何 CR3 更新 - 操作系统可以在其允许的由底层页表映射的内存部分内做它喜欢的事情,并且如果 VM 超出了允许的部分,VMM 会将其捕获为“VMM 页表错误”。这当然使整个事情变得更有效率。

我希望这是有道理的。

于 2013-01-05T22:34:28.857 回答