内存虚拟化|内存虚拟化硬件基础——EPT


文章目录

  • 前言
  • EPT转换开关
  • EPT转换时机
  • EPT转换原理
    • EPT页结构
    • EPT地址转换
【内存虚拟化|内存虚拟化硬件基础——EPT】
前言
  • EPT(Extended Page Table)是Intel为实现内存虚拟化专门增加的硬件特性。
  • 实现内存虚拟化,主要解决的问题是,当CPU运行在VMX非根模式下,它对所有物理内存的读写,需要通过VMM的模拟来实现的。
  • 非根模式下的CPU,仍然要支持实模式,保护模式,保护模式下的三种分页模式以及各种地址转换的表,比如页目录指针表(PDPT),页目录表(PD),页表(PT)等等。当涉及到物理内存的读写时,如果是根模式就直接读写,但这里是非根模式,它是要模拟一个CPU,所有对于主机上资源的访问都要被监控或者被模拟,包括物理内存。因此传统的设计思路是非根模式下CPU对物理内存的访问被认定为敏感指令,会退回到根模式交给VMM处理,VMM负责将这段物理内存转化成主机上真实的物理内存然后返还给虚机CPU使用。
  • 传统的设计思路有两个问题:一是非根模式下的CPU访问物理内存很频繁,会频繁的触发CPU模式切换,开销非常大;二是退回到根模式后,VMM对客户机物理地址的模拟要经过GPA -> HVA -> HPA三个阶段的地址转换,软件实现效率低。
  • 影子页表解决了第二个问题,它的出发点是减少地址转换。基本原理是:当处于非根模式下的CPU有修改CR3的动作时(通常是下一个进程被调度的时候),意味着有页目录地址会被加载到CR3(如果是32-bit分页模式),这时VMM截获这个动作,退回到根模式,VMM中维护了一个hash链表,专用于存放CR3中页目录地址对应的影子地址,VMM拿到页目录地址后计算该地址的hash值并作为key放到hash表中,然后申请一个主机上的物理地址作为页目录的地址放到CR3寄存器中,同时主机上的物理地址也被存放到hash表中,CR3原有的应该被保存的页目录地址被VMM保存起来,当虚拟机进程被调度出去的时候,CR3中应该被保存的页目录地址要放回到进程控制块中,这时VMM会截获这个动作并提供之前保存的页目录地址。VMM在CR3寄存器被修改的过程中,偷天换日,将本应该放到CR3中的地址拿走,替换成自己申请的地址,当客户机要从CR3中取回这个地址时替换回去。影子页表的示意图如下,由于每个进程都有自己的地址空间,因此都有一个CR3的内存值,所以影子页表的Hash链表中,一个Node节点对应存放一个进程的页目录地址。
    内存虚拟化|内存虚拟化硬件基础——EPT
    文章图片
  • KVM通过监听CR3寄存器读写,为每一个在VMX模式下使用CR3加载页表的进程,在主机上维护了对应的页目录和页表(注意,影子页表的说法并不准确,因为主机上除了页表,还维护了页目录,这些都是影子)。CR3指向的是进程的一个内存地址空间,所以主机需要为VMX模式下的所有进程,都维护这样一份影子页目录和影子页表,放在hash表中,当进程被调度,页表被加载时,从hash表中找到对应的影子页目录的地址放到CR3中。影子页表通过增加内存维护成本,减少地址转换的路径。有一定效果,但每个进程的页表和页目录的维护成本也不小,因此进一步引入了EPT机制
  • EPT克服了影子页表使用软件维护GVA->HPA地址转换的缺点,它使用硬件来维护GPA->HPA,因此效率大大提高。而且,影子页表虽然缩短了地址转换路径,但每次虚机进程访问CR3时,都会引起VMX的模式切换,开销很大。影子页表在每次加载和卸载的时候都会引起模式切换,而EPT减少了这种开销,EPT只在缺页的时候才引起VMX模式切换,一旦页表建立好之后,EPT就不再有模式切换的开销,虚机内存的访问一直在客户态。
EPT转换开关
  • EPT是Intel为支持虚拟化的开发的硬件特性,因此使能开关应该在虚拟化相关的域中,secondary processor-based VM-execution contro是VM-execution的一个控制字段,它位于VMCS(Virtual Machine Control State)中,它是一个32bit的字段,其中一个bit就是EPT使能位。
EPT转换时机
  • EPT使能之后,客户态模式下所有物理地址都被识别成guest-physical address,CPU对这些地址的访问需要通过EPT转换成主机上的物理地址。EPT地址转换时机就是CPU访问GPA的时侯。为了让客户机的程序感觉不到自己处于客户态,EPT需要支持实模式,保护模式和保护模式下所有的分页模式,所有这些模式下对物理地址的访问,都要触发GPA地址转换。实模式下,进程的所有线性地址都是GPA;保护模式下,进程页表的物理地址,页目录地址,页表地址,这些都是GPA。
  • 以保护模式下32-bit分页模式为例(CR0.PG = 1)为例,介绍客户态模式下物理页查询过程中的地址转换,假设MMU的输入是一个32bit的进程线性地址:
  1. MMU首先从CR3中取出页目录地址,访问该页目录的内容,此时页目录地址被认为是GPA,会触发EPT页表的查询,返回的HPA指向页目录。MMU取32-bit线性地址的高10位作为索引,在页目录中查找并获取页表地址
  2. MMU拿到页表地址后,访问该页表内容,此地址也被认为是GPA,会触发EPT页表查询,返回一个HPA指向页表。MMU取32-bit线性地址的中间10位作为索引,在页表中查找对应的条目,获取物理页地址
  3. MMU拿到物理页地址后,访问该页内的偏移,再次触发EPT页表查询,返回HPA指向主机的物理页。MMU取32-bit线性地址的最低12位作为偏移,读写物理页的内容。
    注意,EPT转换只有在客户态真正访问GPA内容时才发生。MMU单单获取GPA时不会触发地址转换。
EPT转换原理 EPT页结构
  • Intel处理器设计了EPT的页结构用来将保存GPA到HPA的映射,因此说EPT是硬件支持的,EPT的页结构如下图的咖啡色部分,整个页结构有4级,和4-level分页模式的结构一模一样,只有存放PML4 Table物理地址的地方不一样,4-level将PML4 Table的地址存放在CR3寄存器中;EPT没有,EPT中PML4 Table的地址被称为EPTP,它存放在VMCS中的VM-execution 控制字段。VMM用VMCS来配置VM的运行环境以及控制VM的运行。进入客户态之前,VMM首先通过特殊指令VMPTRLD加载VMCS内存地址的指针,其中就包括EPTP字段,因此理论上EPTP是针对每个虚机而言的,EPT对每个虚机是可以配置的。有人会问,客户态的所有物理地址都是GPA,那么存放EPT物理地址的EPTP是什么地址呢?个人理解,这个地址不是GPA,它非常特殊,因为它是在未进入客户态之前由VMM加载的,不可能是GPA,应该是主机上的地址HPA。
    内存虚拟化|内存虚拟化硬件基础——EPT
    文章图片
EPT地址转换
  • EPT地址转换的输入有两个,一个是客户机的物理地址GPA(Guest Physical Address),一个是PML4 Table的物理地址,指向了EPT的页结构。当运行在客户态下的CPU访问CR3指向的页结构时,如果涉及到对物理内存的内容的访问,就会触发EPT地址转换,Intel硬件接管这个任务,完成转换,步骤如下:
  1. 根据VMCS中的EPTP字段找到页结构的起始地址:PML4 Table的地址,加载对应的PML4 Table内容,PML4 Table中由512个条目,将GPA的高9位作为索引,在PML4 Table中索引PDPT(Page Directory Pointer Table)的地址。
  2. 根据PDPT地址加载PDPT内容,也是512个条目,将GPA的次9位作为索引,在PDPT中索引PDT(Page Directory Table)的地址。
  3. 根据PDT地址加载PDT内容,同样是512个条目,将GPA从高到低的第3个9位作为索引,在PDT中索引页表的地址。
  4. 根据页表的地址加载其内容,同样是512个条目,将GPA从高到底的第4个9位作为索引,在页表中找到页的地址。
  5. 根据页地址,加载页的内容,将GPA的低12位作为索引,在页中找到最终要访问的页的内容。
  • 对EPT页结构中的访问出错可能导致页故障从而引发VM-exit,分下面两种情况:
  1. EPT violation,这种情况典型场景就是页结构不存在,类似于主机上的缺页故障(#PF Page Fault),发生这种故障后CPU会退回到内核态,同时会在VM-exit qualification字段记录EPT violation故障的详细信息。EPT页结构和主机上普通的页结构类似,页表都是故障触发,逐渐填充页结构的过程。在客户态模式下,这是EPT violation故障;在主机上,这就是缺页故障。怎样判断页结构不存在呢?通过查看每个描述页结构条目的低3位(read/write/execute),如果低3位全都为0,就表示指向的下一级页结构不存在(not-present)。这是非页表的情况,如果是页表(Page Table),它的条目的最低位是Present位,可以单独用来表示指向的页是否存在。
  2. EPT misconfiguration,另一种会导致页故障的情况,它是在页结构存在的情况下(页结构低3位的任何一位非0),发现页结构的内容设置不恰当而产生的故障,这种情况是EPT的页结构真的出了配置上的问题而产生的故障,对于EPT misconfiguration,并不会记录详细信息。VM-exit qualification字段为未定义值。
    注意,故障不同于异常,硬件故障后会跳转到相应的处理例程,在处理完之后会重新运行出故障时的指令而非下一条,EPT violation和主机页表中的Page Fault一样,都属于故障。对于使用EPT页表或者主机页表的用户程序来说,当访问到不存在的页结构触发了故障后,硬件会处理然后重新执行,用户程序是感觉不到的。

    推荐阅读