大家好,欢迎来到IT知识分享网。
名词解释
- Guest态
Intel手册中的非根模式(None-Root Mode)。
- Host态
Intel手册中的根模式(Root Mode)。
- EPT
Intel手册中的扩展页表,Extended Page Table。
- PML4
Intle手册中的4级结构页表的第一级(Page Map Level 4)。
- PDPT
页目录指针表,Page Directory Pointer Table。
- PD
页目录,Page Directory。
- PT
页表,Page Table。
前言
EPT是Intel为实现内存虚拟化专门增加的硬件特性。实现内存虚拟化主要解决的问题是,Guest态的CPU对物理内存的读写,不能直接写到HPA,需要VMM进行模拟来实现,即VMM虚拟Guest CPU需要访问的物理内存。
Guest态CPU,仍然要支持实模式、保护模式、保护模式下的三种分页模式以及各种地址转换的表,如PDPT、PD、PT等等。当涉及到物理内存的读写时,如果是根模式就直接读写,但这里是非根模式,它是要模拟一个CPU,所有对于主机上资源的访问都要被监控或者被模拟,包括物理内存。因此,传统的设计思路是非根模式下CPU对物理内存的访问被认定为敏感指令,会退回到根模式交给VMM处理,VMM负责将这段物理内存转化成主机上真实的物理内存然后返还给虚机CPU使用。
传统的设计思路有两个问题:一是非根模式下的CPU访问物理内存很频繁,会频繁地触发CPU模式切换,开销非常大;二是退回到根模式后,VMM对客户机物理地址的模拟要经过GPA -> HVA -> HPA
三个阶段的地址转换,软件实现效率低。
影子页表解决了第二个问题,它的出发点是减少地址转换。其基本原理是:
1)当处于非根模式下的CPU有修改CR3的动作时(通常是下一个进程被调度的时候),意味着有页目录地址会被加载到CR3(如果是32-bit分页模式),这时VMM截获这个动作,退回到根模式;
2)VMM中维护了一个hash链表,专用于存放CR3中页目录地址对应的影子地址。VMM拿到页目录地址后计算该地址的hash值并作为key放到hash表中,然后申请一个主机上的物理地址作为页目录的地址放到CR3寄存器中,同时主机上的物理地址也被存放到hash表中,CR3原有的应该被保存的页目录地址被VMM保存起来;
3)当虚拟机进程被调度出去的时候,CR3中应该被保存的页目录地址要放回到进程控制块中,这时VMM会截获这个动作并提供之前保存的页目录地址。
VMM在CR3寄存器被修改的过程中,偷天换日,将本应该放到CR3中的地址拿走,替换成自己申请的地址,当客户机要从CR3中取回这个地址时替换回去。
影子页表的示意图如下,由于每个进程都有自己的地址空间,因此都有一个CR3的内存值,所以影子页表的Hash链表中,一个Node节点对应存放一个进程的页目录地址。
KVM通过监听CR3寄存器读写,为每一个在VMX模式下使用CR3加载页表的进程,在主机上维护了对应的页目录和页表(注意,影子页表的说法并不准确,因为主机上除了页表,还维护了页目录,这些都是影子)。CR3指向的是进程的一个内存地址空间,所以主机需要为VMX模式下的所有进程,都维护这样一份影子页目录和影子页表,放在hash表中,当进程被调度,页表被加载时,从hash表中找到对应的影子页目录的地址放到CR3中。影子页表通过增加内存维护成本,减少地址转换的路径,有一定效果。但每个进程的页表和页目录的维护成本也不小,因此进一步引入了EPT机制。
EPT克服了影子页表使用软件维护GVA->HPA地址转换的缺点,它使用硬件来维护GPA->HPA,因此效率大大提高。而且,影子页表虽然缩短了地址转换路径,但每次虚机进程访问CR3时,都会引起VMX的模式切换,开销很大。影子页表在每次加载和卸载的时候都会引起模式切换,而EPT减少了这种开销,EPT只在缺页的时候才引起VMX模式切换,一旦页表建立好之后,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。
-
EPTP —— Extended Page Table Pointer
EPTP(extended-page-table pointer)是VMCS中存放EPT页表物理地址的字段,它的格式如下:
- EPTP指向的下一级是PML4 Table,它是页对齐的,因此至少是4K对齐,所以低12 bit没有用,可以拿来复用。其中bit 6是和脏页跟踪有关的标志位,它被置1时,CPU访问EPTP指向的任何下级页结构的时候,Access位都会被置1,最后的页表项中的Dirty位会被置1。
- EPTP bit 12之上的字段用来存放下一级表PML4 Table的物理地址。
PML4E —— Page Map Level 4 Entry
- Accessed flag:bit 8访问标志位。当EPTP中的accessed and dirty flags置位时,CPU每次通过EPT多级页表结构转换物理地址时,只要使用到这一级的页表项,就需要将Accessed flag置位。
- Physical address:bit 12 ~ bit (N-1),存放下一级页表结构的物理地址。
PDPT —— Page Directory Pointer Table
- Accessed flag:bit 8访问标志位。当EPTP中的accessed and dirty flags置位时,CPU每次通过EPT多级页表结构转换物理地址时,只要使用到这一级的页表项,就需要将Accessed flag置位。
- Physical address:bit 30 ~ bit (N-1),存放下一级页表结构的物理地址。
PDE —— Page-Directory Entry
- Accessed flag:bit 8访问标志位。当EPTP中的accessed and dirty flags置位时,CPU每次通过EPT多级页表结构转换物理地址时,只要使用到这一级的页表项,就需要将Accessed flag置位。
- Physical address:bit 12 ~ bit (N-1),存放下一级页表结构的物理地址。
PTE —— Page Table Entry
- Accessed flag:bit 8访问标志位,当CPU对该页表项指向的物理页有访问操作时,读写操作都算,会将Dirty flag置位。
- Dirty flag:bit 9脏页标志位,当CPU对该页表项指向的物理页进行写操作时,会将Dirty flag置位。
- Physical address:bit 12 ~ bit (N-1),存放下一级页表结构的物理地址。
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 violation与EPT misconfiguration
对EPT页结构中的访问,如果页不存在或者出错,可能导致页故障,如果VMCS
的VM-execution control
的EPT-violation
字段为0,页访问出错会触发VM-exit,分下面两种情况:
- 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位,可以单独用来表示指向的页是否存在。
- EPT misconfiguration
另一种会导致页故障的情况,它是在页结构存在的情况下(页结构低3位的任何一位非0),发现页结构的内容设置不恰当而产生的故障。这种情况是EPT的页结构真的出了配置上的问题而产生的故障,对于EPT misconfiguration,并不会记录详细信息。VM-exit qualification字段为未定义值。
注意,故障不同于异常,硬件故障后会跳转到相应的处理例程,在处理完之后会重新运行出故障时的指令而非下一条,EPT violation和主机页表中的Page Fault一样,都属于故障。对于使用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(GPA),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时不会触发地址转换。
Q&A
Q:EPT violation和EPT misconfig都是缺页故障,两者有什么区别吗?
注:原文笔者所谓的故障实际上应该是异常,而原文中的异常实际上应该是中断。
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/149707.html