Intel SDM Chapter 28: VMX Support for Address Translation

下文中出现的VMCS[x]并不是指在VMCS中偏移量为x的位置存放的数据。此处应将x理解为VMREADVMWRITE指令的操作数,VMCS[x]就是VMREAD xVMWRITE x会访问到的那个Field。之所以必须如此,是因为VMCS中的Field具体的偏移量是Implementation Defined的,只能通过手册第三卷附录B中提供的编码访问。

VMX扩展中提供的功能,其是否存在不是通过CPUID指令查询,而是通过MSR查询。由于特性位较多,在正文中不一一叙述,需要时查手册第三卷附录A即可。

Secondary Processor-Based VM-Execution Controls位于VMCS[0x401E](32 bit)

Virtual Processor Identifiers (VPIDs)

VMX在PCID之外又引入了VPID,用于区分不同虚拟机的TLB条目。VPID功能需要通过设置Secondary Processor-Based VM-Execution Controls.Enable VPID[bit 5]来开启,开启后VPID由VMCS[0x0000](16 bit)决定。

VPID的取值可总结如下:

  • 不处于VMX模式,或处于VMX Root模式时,VPID为0
  • 处于VMX Non-Root模式,但VPID未启用时,VPID为0
  • 处于VMX Non-Root模式,且VPID启用时,VPID为VMCS[0x0000](16 bit)
    • 一旦VPID启用,则VPID不允许为0,否则会在VM Enter时发生异常

Extended Page Table (EPT)

Overview

EPT功能即在通常的页表地址翻译之外,再增加了一层页表翻译机制,将地址翻译过程改为了Linear Address -> Guest Physical Address -> Host Physical Address(若Guest未开启页表则为Linear Address -> Host Physical Address)。EPT功能需要通过设置Secondary Processor-Based VM-Execution Controls.Enable EPT[bit 1]来开启。

若不开启EPT模式,则Guest(即VMX Non-Root模式下)必须开启页表(即要求CR0.PE = 1CR0.PG = 1)。只有在EPT模式下,才能通过设置Secondary Processor-Based VM-Execution Controls.Unrestricted guest[bit 7],来解除这个限制,允许Guest运行在实模式或未开启分页的保护模式。

EPT的根节点由EPT Pointer(EPTP)指定,EPT Pointer就相当于CR3的地位,它位于VMCS[0x201A]/VMCS[0x201B](64 bit full/high)。目前EPT采用与64位分页模式类似的4级页表(但Intel保留采用更多级或更少级的权力),其各级页表项格式如下:

EPT Paging Structures

  • EPTP的第0-2位为EPT paging-structure memory type,表示walk EPT时采用的Memory Type,目前只允许取0(表示UC)或6(表示WB)
  • EPTP的第3-5位为EPT page-walk length - 1,由于目前所有Intel CPU都采用4级EPT,故总是取3
  • EPTP的第6位为Enable A/D Bit,取1则启用Access/Dirty位,取0则不启用
  • 各级页表项的第0位为R (Read),取1表示可读
  • 各级页表项的第1位为W (Write),取1表示可写
  • 各级页表项的第2位为X (eXecute),取1表示可执行
    • Secondary Processor-Based VM-Execution Controls.Mode-based execute control for EPT[bit 22]取1,则该位取1仅表示对于Guest的内核页可执行,不表示对于Guest的用户页可执行
  • 末级页表项的第3-5位为EPT Memory Type,用于决定内存的Memory Type,详下
  • 末级页表项的第6位为Ignore PAT (IPAT),用于决定内存的Memory Type,详下
  • 各级页表项的第7位为PS (Page Size),取1表示大页,取0表示指向下一级页表
  • 各级页表项的第8位为A (Access),取1表示Accessed
  • 末级页表项的第9位为D (Dirty),取1表示Dirty
  • 各级页表项的第10位为XU (eXecute for User),取1表示对于Guest的用户页可执行
    • 仅当Secondary Processor-Based VM-Execution Controls.Mode-based execute control for EPT[bit 22]取1时有效,否则该位会被忽略
  • 末级4K页表项的第61位为SPP (Sub-Page write Permission),取1表示该页的128 Byte子区域可以独立设置写权限,详下
  • 各级页表项的第63位为SVE (Suppress #VE),取1则表示对该页的访问造成的EPT Violation不能转换成#VE,必须直接引起VM Exit,详下
  • 其余为Ignored或Reserved,其中Ignored位可以被软件使用

EPT中取消了P (Present)位,R、W、X(及XU,若该位有效)皆为0即视为Non-Present,会引起EPT Violation

一旦启用Access/Dirty位,则对Guest Paging Structure的访问一律视为写入,若其对应的EPT映射为不可写,则会引起EPT Violation。这里的逻辑是Guest访问页表的同时也会设置A/D位,因此需要写权限(无论某一次特定访问是否真的设置了A/D位)。此外,和通常的页表一样,A/D位需要手动清空,并且清空后需要刷新TLB才能引起下一次的A/D位设置。

EPT-Induced VM Exits

在walk EPT的过程中,如果遇到了不合法的页表项,就会产生EPT MisconfigurationVM Exit No.49)。下列情况属于不合法:

  • 页表项的R = 0, W = 1,即只读却可写,矛盾
  • 若CPU不支持只可执行的EPT页,则R = 0, X/XU = 1的页表项不合法
    • 通过MSRIA32_VMX_EPT_VPID_CAP可以检查CPU是否支持只可执行的EPT页
  • Reserved Bit被设置为1,或末级页表项的EPT Memory Type取了2、3或7(这三个值为Reserved,没有对应的Memory Type)

在walk EPT的过程中,如果遇到以下情况,则会引起EPT Violation:

  • 页表项Non-Present
  • 对不可读页进行读取
  • 对不可写页进行写入
  • 对不可执行页进行取指令
    • Secondary Processor-Based VM-Execution Controls.Mode-based execute control for EPT[bit 22]取1,则X位作用于Guest内核页,XU位作用于Guest用户页
    • 否则不可执行只取决于X位

EPT Violation通常会导致一个VM Exit(VM Exit No.48 EPT Violation)。但是,如果开启了Secondary Processor-Based VM-Execution Controls.EPT-violation #VE[bit 18],则EPT Violation可以被转化为#VE(不总是能转化,有时还是会引起VM Exit),其中#VE为处理器异常(Exception),和#GP、#PF类似。特别地,如果引起EPT Violation的页表项的第63位(Suppress #VE)为1,则无论如何都不会转换成#VE,一定会直接引起VM Exit。

EPT Violation转化成#VE后,和别的异常一样,根据VMCS中Exception Bitmap的配置,可能还是会引起VM Exit(不过此时Exit Reason不同,将会是VM Exit No.0),也可能会将异常交给Guest处理,从而避免一个VM Exit。

【TODO: 25.5.6 EPT 转化 #VE 的条件】

Sub-Page Write Permissions

Secondary Processor-Based VM-Execution Controls.Sub-page write permissions for EPT[bit 23]取1时,Sub-Page Write Permission功能开启。这个功能允许不可写的4K页中划分出32个128 Byte大小的Sub-Page,取其中一部分单独设置为可写。

具体来说,Sub-Page Write Permission只适用于满足以下条件的页:

  • 该页为一个4K页
  • 该页的EPT表项的第61位(SPP)取1
  • 该页不可写入

并且不适用于以下访问情形(即使满足上述条件):

  • 在Transactional Region中进行的写入(即SPP与TSX技术不兼容)
  • Enclave对一个位于Enclave的ELRANGE中的地址的写入(即SPP与SGX技术不兼容)
  • SGX指令对Enclave Page Cache (EPC)的写入(即SPP与SGX技术不兼容)
  • 对Guest Paging Structure的A/D位的更新
  • 若启用EPT的A/D位,则page walk时对Guest Paging Structure的访问也不适用

Sub-Page Write Permission特性添加了一个新的4级「页表」,它的根节点是SPPTP (Sub-Page Permission Table Pointer),位于VMCS[0x2030]/VMCS[0x2031](64 bit full/high)。它的各级页表项最低位为P (Present),第12-63位表示下一级页表的Host物理地址,其余为保留位。它的末级页表项称为SPP Vector,对于其对应页的第S个Sub-Page,其第2S位表示该Sub-Page是否可写,取1即可写,奇数位则为保留位,必须为0。

在查询Sub-Page Write Permission的过程中,若遇到Present位取0,则产生一个SPP Miss,若遇到保留位取1,则产生一个SPP Misconfiguration。这两者统称SPP-related Event,会导致VM Exit(VM Exit No.66 SPP-related Event)。

Page-Modification Logging

当Access/Dirty位被启用时,还可以进一步使用page-modification logging特性记录对Guest Physical Address的写入。通过将Secondary Processor-Based VM-Execution Controls.Enable PML[bit 17]设置为1,可以启用该特性。

开启page-modification logging后,可以通过PML Address(VMCS[0x200E]/VMCS[0x200F](64 bit full/high))指定一块4KB大小的物理内存(PML Address是Host物理地址),其中允许存放512条64位的记录,每条记录就是一次Guest写入操作的Guest Physical Address。

开启page-modification logging后,会新增一个Guest Non-Register State.PML indexVMCS[0x0812](16 bit)),它被用作上述4KB大小的PML页的index。当PML index取值为0-511时,一次Guest写入操作会导致这次写入的Guest Physical Address记录到PML页的第PML index条记录,并且将PML index减一(注意PML index是从高向低进行步进的)。当PML index的取值不在0-511范围内,而Guest又进行了写入操作时,就会引发Page-Modificaton Log FullVM Exit No.62),此时就需要在Hypervisor中用VMWRITE指令将PML index重设为511。

EPT and Memory Typing

涉及EPT的Memory Type有两个,首先是walk EPT时,访问EPT各级页表项所采用的Memory Type:

  • CR0.CD = 0,则采用的Memory Type由EPTP的第0-2位决定,取0表示UC,取6表示WB
  • CR0.CD = 1,则采用的Memory Type为UC

其次是Guest访问内存时,采用的Memory Type,它由两个因素决定:

  • EPT Memory Type:即EPT中最后一级页表项的第3-5位,起相当于MTRR的作用
    • 取0表示UC,取1表示WC,取4表示WT,取5表示WP,取6表示WB,这与MTRR中Type的含义相同
    • 此时MTRR完全不起作用
  • PAT Memory Type:
    • CR0.PG = 0,则PAT Memory Type为WB
    • CR0.PG = 1,则PAT Memory Type为Guest页表翻译时根据MSR[IA32_PAT]确定的PAT Memory Type

最终产生的Memory Type如下:

  • CR0.CD = 0
    • 若末级页表项的IPAT = 0,则Memory Type就是将EPT Memory Type当做MTRR Memory Type和PAT Memory Type合并后的结果
    • 若末级页表项的IPAT = 1,则Memory Type就是EPT Memory Type
  • CR0.CD = 1,则Memory Type为UC

Caching Translation Information

Cached Information

  • Linear Mappings
    • Linear Translations:从Linear Page Number映射到(Guest) Physical Page Frame及相关信息
    • Linear Paging-Structure-Cache Entries:从Linear Address的高位映射到对应的(Guest) Paging-Structure的(Guest) Physical Address及相关信息
  • Guest-Physical Mappings
    • Guest-Physical Translations:从Guest Physical Page Number映射到Host Physical Page Frame及相关信息
    • Guest-Physical Paging-Structure-Cache Entries:从Guest Physical Address的高位映射到对应的EPT Paging-Structure的Host Physical Address及相关信息
  • Combined Mappings
    • Combined Translations:从Linear Page Number映射到Host Physical Page Frame及相关信息
    • Combined Paging-Structure-Cache Entries:从Linear Address的高位映射到对应的Guest Paging-Structure的Host Physical Address及相关信息

Creating and Using Cached Translation Information

当EPT未被使用时(非VMX模式、VMX Root模式或VMX Non-Root模式但未启用EPT):

  • 翻译Linear Address的过程中,只会创建Linear Mappings,不会创建Guest-Physical或Combined Mapping
  • 对于非Global的Linear Mapping,需要VPID和PCID都匹配;对于Global的Linear Mapping(仅Linear Translatoion支持Global条目),则需要VPID匹配
    • 即Guest的Global页和Host的Global页是隔离的

当EPT被使用时:

  • 使用EPT时,不会创建也不会查询Linear Mappings
  • 翻译Guest Physical Address的过程中,可能会创建Guest-Physical Mappings,所创建的Mapping会绑定到当前的EPT根节点(即EPT-PML4-table的Host物理地址,也就是EPTP中指定的地址,简称EP4TA),作为索引
  • 查询TLB/Paging-Structure Cache时,需要Guest-Physical Mapping的EP4TA和当前的EP4TA匹配
  • 翻译Linear Address到Host Physical Address的过程中,可能会创建Combined Mappings,所创建的Mapping会绑定到当前的(PCID, VPID, EP4TA)
  • 查询TLB/Paging-Structure Cache时,需要以当前的(PCID, VPID, EP4TA)作为索引来查询Combined Mapping

Invalidating Cached Translation Information

首先,以下操作会引起缓存在TLB/Paging-Structure Cache的Translation Information被清空:

  • 与VMX无关的普通清TLB操作(即第4章中介绍的操作),会针对当前VPID对应的Linear Mapping和Combined Mapping进行清空操作
    • Linear Mapping的索引为(VPID, PCID, Address),取索引为(VPID, *, *)的子集,然后对其施加第4章中描述的清空操作即可
    • Combined Mapping的索引为(VPID, PCID, EP4TA, Address),取索引为(VPID, *, *, *)的子集,然后对其施加第4章中描述的清空操作即可(即对所有的EP4TA对应的Combined Mapping都要进行清空)
  • 发生EPT Violation时,会将引起EPT Violation的Guest Physical Address并当前EP4TA对应的Guest-Physical Mapping清空。若该Guest Physical Address是由一个Linear Address翻译而来的(即不是walk Guest页表得到的),则还要清空Linear Address并当前VPID、PCID、EP4TA对应的Combined Mapping。
    • 这和Page Fault造成的对TLB/Paging-Structure Cache的清空类似
  • Enable VPID = 0,VM Entry和VM Exit会清空所有VPID = 0对应的Linear Mapping和Combined Mapping
    • 对所有PCID、EP4TA对应的映射都会进行清空,只要VPID = 0,下同

其次,引入了INVVPIDINVEPT两条指令:

  • INVVPID指令,接受一个寄存器操作数(称为INVVPID Type)和一个128位的内存操作数(称为INVVPID Descriptor)。
    • INVVPID Descriptor的第0-15位为VPID,第64-127位为Linear Address,其余位保留为0
    • INVVPID Type目前有四种,分别为
      • Type 0, Individual Address:清空(VPID, Linear Address)对应的Linear Mapping和Combined Mapping
      • Type 1, Single Context:清空VPID对应的Linear Mapping和Combined Mapping
      • Type 2, All Context:清空除VPID = 0外所有的Linear Mapping和Combined Mapping
      • Type 3, Single Context Retaining Globals:清空VPID对应的Linear Mapping和Combined Mapping,除了Global的Mapping
  • INVEPT指令,接受一个寄存器操作数(称为INVEPT Type)和一个128位的内存操作数(称为INVEPT Descriptor)。
    • INVEPT Descriptor的第0-63位为EPTP,其余位保留为0
    • INVEPT Type目前有两种,分别为
      • Type 1, Single Context Invalidation:清空EP4TA对应的所有Guest-Physical和Combined Mapping(针对所有VPID、PCID)
      • Type 2, Global Invalidation:清空所有的Guest-Physical Mapping和Combined Mapping