Intel SDM Chapter 28: VMX Support for Address Translation
下文中出现的VMCS[x]
并不是指在VMCS中偏移量为x
的位置存放的数据。此处应将x
理解为VMREAD
、VMWRITE
指令的操作数,VMCS[x]
就是VMREAD x
、VMWRITE 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 = 1
及CR0.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保留采用更多级或更少级的权力),其各级页表项格式如下:
- 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的用户页可执行
- 若Secondary Processor-Based VM-Execution Controls.Mode-based execute control for EPT
- 末级页表项的第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时有效,否则该位会被忽略
- 仅当Secondary Processor-Based VM-Execution Controls.Mode-based execute control for EPT
- 末级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 Misconfiguration(VM Exit No.49
)。下列情况属于不合法:
- 页表项的R = 0, W = 1,即只读却可写,矛盾
- 若CPU不支持只可执行的EPT页,则R = 0, X/XU = 1的页表项不合法
- 通过MSR
IA32_VMX_EPT_VPID_CAP
可以检查CPU是否支持只可执行的EPT页
- 通过MSR
- 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位
- 若Secondary Processor-Based VM-Execution Controls.Mode-based execute control for EPT
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 index(VMCS[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 Full(VM 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,下同
其次,引入了INVVPID
和INVEPT
两条指令:
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