下图所示的是 Nested Paging 的物理结构。运行在 NPT 情况下,虚拟机 CPU 的 CR3 寄存器指向的是客操作系统上页表的 gpa, nCR3 指向的是由 VMM维护的第二维页表的 hpa。 在硬件的驱动下,客操作系统的gva 首先被第一维页表翻译成 gpa, 然后 VMM 上的第二维页表又将该 gpa 翻译称 hpa。 物理的页表遍历硬件逻辑是相当复杂的,其中第一维页表 CR3 及每一级翻译输出的 gpa 都要经过第二维页表的翻译才能转换成linux hpa, 因此翻译一个 gva 可能需要经过 20 多次的物理内存访问, 导致较高的物理延迟。 在 NPT 情况下,已有的 TLB 用来缓存 gva 到 hpa 的映射。此外,支持 NPT 的 AMD 的处理器一般都提供了一个 Nested TLB 来缓存 gpa 到 hpa 的映射, 以平衡在 TLB 的 “Cache Miss” 情况下 NPT 二维页表遍历延迟较高所带来的性能损失。 另外一个和 NPT 相关的问题是物理页属性控制问题,在 NPT 情况下,针对一个 CPU 上运行的客操作系统,有两套控制寄存器 (CR0 ,CR4 ,EFER ,PAT ,MTRRx) 以及两层页表上的属性位来控制一个物理页的访问属性, 针对每个控制寄存器和属性linux位,NPT 一般采用 guest 和 host 两级的交集来执行控制,如只有当 guest 和 host 两级的页表和控制寄存器都允许写某物理页时,该物理页才允许被写。 MTRRx 的处理比较特殊,目前客操作系统的MTRR 寄存器实际上对页的访问控制是无效的, 一方面 AMD-V 硬件上没有对 MTRR 寄存器建立影子,另一方面 KVM 截取客操作系统对 MTRR 的访问的处理比较简单,在 MTRR 被设置时会重新初始化整个第二维的页表, 释放所有的页表页,当以后 KVM 上“page fault” 重新建立这些页表页时,这些 guest 层的 MTRR 的设置才会同步到页表项中去linux。 在 NPT 情况下,客操作系统对其自己的页表 ( 第一维页表 ) 有完全的控制,因此 KVM 不必要截获客操作系统对页表的修改。另外,由于第二维页表执行的是从 gpa 到 hpa 的映射,在一个虚拟机运行过程中,KVM 只需要维护一个唯一的第二维页表,也就免去了截获客操作系统切换 CR3 的开销。 当然,NPT 的另外一个优点是比 Shadow Paging 节省很多 VMM 层的页表页, 减少物理内存的总体消耗。很多测试表明,在采用 NPT 技术后,虚拟化应用的性能会显著提高,内存分配密集型的应用尤其如此。
|