VM guest虚拟机内的进程是否有可能使用VMX(AMD-V,VT-x)CPU指令,然后由外部VMM处理而不是直接在CPU上处理?
编辑:假定外部VM使用VMX本身来管理其虚拟来宾计算机(即,它在Ring -1中运行)。
如果有可能,是否有任何VMM的实现都支持模拟/拦截VMX调用(VMware,Parallels,KVM等)?
最佳答案
英特尔的VT-x或AMD的AMD-V都不支持硬件中的完全递归虚拟化-在CPU中,CPU以call
/ ret
对的相同方式保留嵌套虚拟化环境的层次结构。
逻辑处理器仅支持两种操作模式:主机模式(在Intel术语中称为VMX根模式,在AMD的术语中称为管理程序)和来宾模式(在AMD手册中称为,而在Intel的手册中称为VMX非根模式)。
这意味着层次结构扁平化,CPU对每个虚拟化环境都进行了相同的处理-CPU不知道VM层次结构的深度是多少级。
尝试在访客内部使用他们自己的虚拟化指令将对监视器(VMM)产生控制。
但是最近出现了一些对加速常用虚拟指令的支持,从而使嵌套VM成为可能。
我将尝试分析实现嵌套虚拟化所要面对的问题。
我并没有处理全部问题,而是在考虑基本情况,而忽略了涉及硬件虚拟化的所有部分。本身与软件虚拟化一样有问题的部分。
注意
我不是虚拟化技术专家,也没有任何经验,欢迎进行更正。
该答案的目的是使读者从概念上相信嵌套虚拟化是可能的,并概述了要面对的问题。
VT-x
逻辑处理器通过执行vmxon
进入VMX操作-进入模式后,处理器立即进入root模式。
根模式是VMM的模式,它可以启动,恢复和处理VM。
然后,VMM使用vmptrld
设置当前的VMCS(VM控制结构)-VMCS包含虚拟化来宾所需的所有元数据。
VMCS的读写不是通过直接内存访问‡,而是通过vmread
和vmwrite
指令进行。
最后,VMM执行vmlaunch
以开始执行来宾。
接受虚拟机
现在,逻辑处理器正在虚拟环境中执行。
假设guest虚拟机本身就是VMM,我们称其为非根VMM-它需要重复上述步骤。
但是,英特尔在其手册中有明确规定(手册3-第25.1.2章):
以下说明导致在VMX非root用户操作中执行时,VM退出:
[...]
对于VMX引入的说明也是如此,其中包括:
[...],VMLAUNCH
,VMPTRLD
,[...]和VMXON
vmxon
该指令导致VM退出,根VMM在其最后一个vmlaunch
之后从指令恢复,可以检查VMCS退出的原因并采取适当的措施。
我不是经验丰富的VMM编写者,所以我不确定根VMM必须完全模仿该指令执行什么操作-因为在VMX根模式下执行vmxon
将会失败,并且先执行vmxoff
,然后执行vmxon
,VM区由非根VMM似乎是一个安全漏洞(或导致它的隐患),我相信所有根VMM要做的就是记录来宾现在处于“VMX根模式”。
在这里引号是必需的:仅当根VMM将控制权交还给非根VMM时,该模式才存在于软件中,而CPU将处于非根VMX模式。
之后,非根VMM将尝试使用vmptrld
设置当前VMCS。vmptrld
将导致VM退出,并且根VMM再次处于控制状态-如果CPU不支持VMCS shadowing,则根VMM必须记录由非根VMM给出的指针现在是当前VMCS-如果CPU可以。支持VMCS遮盖VMM,将的VMCS链接指针字段设置为 VMCS(用于虚拟化非根VMM的指针)到非根VMM给出的VMCS。
VMM以一种或另一种方式知道哪个虚拟化VMCS是活动的。
由非根VMM执行的vmread
和vmwrite
将或不会导致VM退出。
如果激活了VMCS阴影,则CPU不会执行VM退出操作,而是读取活动VMCS中由VMCS链接指针指向的VMCS(称为阴影VMCS)。
这将加速嵌套虚拟机的虚拟化。
如果未激活VMCS阴影,则CPU将退出VM,并且根VMM必须模拟读取/写入。
最后,非根VMM将启动其VM-这是一个嵌套VM。vmlaunch
将触发虚拟机退出。
根VMM必须做一些事情:
vmlaunch
/ vmresume
。 梦想中
现在,CPU正在执行嵌套VM(VVM-虚拟VM?)。
当敏感指令或事件导致VM退出时会发生什么?
从处理器的角度来看,虚拟化只有两个级别:根VMX模式和非根VMX模式。
由于访客处于非root用户VMX模式下,因此控制权将转移回root VMX模式代码-即root VMM。
现在,根VMM必须了解该事件是来自其VM还是来自其VM的VM。
这可以通过跟踪
vmlaunch
/ vmresume
的使用并检查VMCS中的位来完成。如果将VM出口定向到非根VMM,则根VMM必须加载其原始VMCS,最终在其中设置非根VMM的链接,更新非根VMM VMCS状态位并执行
vmresume
。如果将VM出口定向到该出口,则根VMM将像处理其他任何VM出口一样处理它。
梦中的梦
如果我们想在嵌套VM中创建VM怎么办?
虚拟虚拟VM(VVVM)的种类。
有两件事要注意:
即使VVVM有3个级别,它也不是非根非根VMM,它是用于虚拟化它的第一个和/或唯一的管理器。
从安全角度来看,根VMM是薄弱环节。
从支持1级嵌套到n级嵌套(再次我在这里没有经验),VMM可能不需要太多的工作,但是仍然需要上面概述的特殊支持。
这不像启动VM那样容易,CPU会照顾所有其他一切。
显卡
在AMD-v中没有root或non-root模式,CPU开始使用
vmrun
执行VM,该vmrun
带有指向VMCB(VM控制块)的指针,该VMCB具有与Intel VMCS相同的作用。根据
vmload
,CPU处于访客模式。VMCB已缓存,但只能通过常规内存访问来读取。
vmsave
/ vmrun
指令显式加载要缓存的VMCB字段并从缓存中保存。该接口比Intel的接口更简单,但功能同样强大-即使涉及嵌套虚拟化。
假设我们在VM内部,并且代码执行
vmrun
-因此我们在虚拟化VMM。从技术上讲,VMM可以选择
VMRUN
何时触发或不触发VM退出。然而,实际上,AMD-v当前始终要求前者:
以下条件被视为非法状态组合:
[...]
*
vmrun
拦截位清除因此,根VMM(我将使用与Intel情况相同的术语)将获得控制权,并且必须模拟
vmrun
(因为硬件仅支持单一级别的虚拟化)。根VMM可以保存当前VMCB并将其与非根VMM VMCB合并,并像Intel一样继续使用
vmrun
。退出后,根VMM必须确定出口是定向到该出口还是定向到非根VMM,这又可以通过跟踪VMCB中的
vmrun
和控制位来完成。再次做梦
我们已经相对容易地在虚拟机内部设置了虚拟机-现在退出虚拟机时会发生什么?
根VMM接收退出,并且如果定向到非根VMM,则必须还原其原始VMCB并继续运行(即,将
vmsave
与原始VMCB一起使用)。AMD-v通过考虑其地址来宾地址,从而支持
vmload
和ojit_code指令的快速虚拟化,因此可以进行通常的页面嵌套虚拟化。再次提出盗梦空间
与Intel情况一样,只要VMM支持该功能,就可以再次嵌套虚拟化。
针对英特尔案件提出的关键安全警告同样适用于AMD的警告。
‡由于其实现定义的格式,并且存储区域可以用作溢出区域,因此不能实时更新
关于assembly - 是否可以在VM中使用VMX CPU指令?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/42597774/