xMP:Selective Memory Protection for Kernel and User Space

需要的背景知识

altp2m

  • p2m: guest Physical memory to machine physical

    p2m代表从客户机物理地址到机器真实物理地址的内存管理层。这一层是为了多个VM之间的隔离。在XEN中,这一层叫Hardware Assisted Paging(hap).

  • altp2m

    ​ 而 altp2m允许为每个VM创建多个EPT表,并且Intel已经支持了这种特性,在VMCS结构中最多允许有512个EPT指针。

    ​ 因为当VM的某个访问页面的权限出问题了的时候,会陷入的VMM,在VM内部并不知道外面做了什么事情。而有的时候对于多个vcpu的系统来说,对于一块页面访问出现了权限问题,可能要放松对于该页面的权限,但是这会导致别的vcpu可能会因为竞争关系访问到宽松权限后的权限,这就会导致有安全问题,于是允许为不同的vcpu设置不同的stage2页表,就可以避免这种问题。当然也可以在访问的时候暂停别的vcpu,这种方案会导致很多的overhead。也可以采用软件模拟的方式,捕获的访问的异常,然后在需要放松权限的地方,陷入到VMM进行模拟。(这种方式对于XEN好像不太友好。原话是这样的:This solution, while supported in Xen, is not particularly ideal either as Xen’s emulator is incomplete and is known to have issues that can lead to guest instability. )

    ​ 利用这种特性,可以将VM映射到不同的物理页,也可以将VM对同一物理页有不同的权限。总之就是允许stage2的页表更加灵活,并且有多个。

#VE:Virtualization Exception

​ #VE是intel的CPU提供的一个特性。原本一些异常的操作会导致VM exit,现在允许将一些设定的情形不再导致VM exit,而是出发一个#VE,然后再guest中进行处理,减少开销。

​ 开启#VE需要设置 EPT-violation #VE” VM-execution control 。当发生VE的时候,CPU会将关于异常的信息保存到 virtualization-exception information area。一些VMM允许guest访问这个area,并改一些这个area的设置,来防止发生VM exit。

​ 特别的,EPT的访问再没设置VE时候都会导致VM exit。如果设置了VE,一些特定的EPT违规行为就会触发VE。page entry的第63位bit设置则表明抑制VE。一些EPT违规的情形能够设置为VE参考手册 卷3-25.5.7。

​ 具体来说,如果VMCS中的异常位图的第20位(#VE)为1,则该VE会导致VM exit,并将信息存入VMCS中VM exit区域。如果该位为0并且是没有导致VM exit的情况则直接在guest中使用IDT表中的20号中断,如果导致VM exit,则会在 IDT-vectoring information field 中存入异常信息。

VMFUNC

​ VMFUNC是一条Intel CPU提供的指令。详情参考手册卷3-25.5.6

​ 相较于hypercall使用的VMCALL指令而言,VMFUNC是在guest中运行VMM的函数,不会导致VM exit。 而hypercall是向VMM请求服务,会导致VM exit,将控制权转至VMM。

MPK:Memory-Protection Key

​ MPK是Intel CPU提供的一种特性,用以页级粒度的保护。它只针对数据获取的权限(accessable,writable),没有针对指令获取。并且只有64位时候有MPK,32位没有。该特性使得能够给用户态提供申请保护,而不用陷入内核修改页表项,减小了开销。

​ MPK最多提供16个key(stage1 page entry中的(59-62)4个bit位。)。对于用户态:CR4.PKE决定了从用户态地址获取页面的MPK开启。PKRU寄存器(32位)中存放了不同的key的权限。对于内核态:CR4.PKS决定了从内核态地址获取页面的MPK的开启,IA32_PKRS MSR寄存器(64位寄存器,但是低32位存放了权限,高32位必须为0)存放了不同key的权限。

​ 对于每个key的权限,用两个bit表示,所以16个key就是32位。 偶数位是access-disable bit,奇数位是write-disable bit。

​ kernel提供了syscall给用户态用以申请MPK。详情见

EPTP switch

​ EPTP switching 是VMFUNC 0.这个函数允许在guest中为自己切换EPT表,但是这些EPT表是提前在hypervisor中配置好的。详情见手册卷3-25.5.6.3

​ 寄存器ECX用以选择EPTP。Intel现在最多支持512个EPTP,所以ECX超过512就会导致VM exit。

Impletment

buddy allocator

​ 对于内存分配器中的buddy allocator,增加了__GFP_XMP标志位,用以申请xMP domain区域的页。通过8个bit来分配256个domain。利用altp2m可以切换每个domain的view(不同权限)

slab allocator

​ slab是建立在buddy之上,更加细粒度的分配器。它将一页分成了多个部分,分配给一些特定的结构,并且有专门的slab cache用于分配和释放内核的数据结构(例如task_struct)。

​ xMP允许在使用slab的时候,将slab放到xMP domain中,因为他是建立在buddy之上的。每当slab cache 要申请新的页时,就可以利用xMP的接口申请xMP domain的页。

Switches across Execution Contexts

上下文切换

​ 在task_struct中增加了domian index字段,用于识别当前thread处于何种xMP view。该字段初始值为最严格的domain view。 当要进入domain区域的时候会切换index值,从而切换权限。之后再上下文切换的时候index值相应的会保存。

硬中断

​ 在硬件中断的时候,将view切换成最严格的domain,防止潜在的中断处理程序问题访问受保护的内存。然后当结束中断返回时,如果要访问xMP domain的内容,会产生一个#VE(原本因为权限问题会陷入VMM),然后#VE handler 处理,验证thread 访问domain的合法性,然后切换domain view,然后继续运行。

软中断

​ 软中断指的是硬件中断中断之后,中断的下半部分机制,这部分kernel由软件实现。(软件中断和软中断在中文上有区别,因为翻译问题)二者区别参考

[知乎]: https://zhuanlan.zhihu.com/p/80371745 “知乎的解答”

​ 这部分利用Linux的(CONFIG_RCU_NOCB_CPU),不用软中断处理,而是起另一个线程来处理,这样就可以根据不同的线程可能要在callback中访问xMP domain,就可以分别给每个线程处理irq时候起的线程进行配置。(这部分还不是特别明白,先这么写)

User space API

​ 创建了四个系统调用,类似MPK的系统调用,创建sys_xmp_{alloc,free,mprotect},但是他不能像MPK那样在用户空间使用VMFUNC指令,所以新建了一个系统调用sys_xmp_enter,用以进入xMP domain,并更新domain view。