x86 平台中的 KVM 影子页表处理

2024-04-29

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

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

Thanks!


我使用 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 页表错误”。这当然会让整个事情变得更有效率。

我希望这是有道理的。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

x86 平台中的 KVM 影子页表处理 的相关文章

随机推荐