是否可以在VM中使用VMX CPU指令?

Joh*_*ith 3 cpu virtualization x86 assembly virtual-machine

VM guest虚拟机中的进程是否可能使用VMX(AMD-V,VT-x)CPU指令,然后由外部VMM而不是直接在CPU上处理?

编辑:假设外部VM使用VMX本身来管理其虚拟客户机(即它在Ring -1中运行).

如果有可能支持模拟/拦截VMX调用(VMware,Parallels,KVM,......)的VMM实现?

Mar*_*oom 10

英特尔的VT-x和AMD的AMD-V也不支持在硬件中实现完全递归的虚拟化 - 其中CPU以与call//相同的方式保持嵌套虚拟化环境的层次结构ret.

逻辑处理器仅支持两种操作模式:主机模式(在英特尔术语中称为VMX根模式,在AMD中称为虚拟机管理程序)和访客模式(在AMD的手册和英特尔的VMX非根模式中称为).
这意味着一个扁平化的层次结构,其中每个虚拟化环境由CPU处理相同 - CPU不知道VM的层次结构有多少级别.

尝试在guest虚拟机内使用虚拟化指令将产生对监视器(VMM)的控制.
但是最近出现了一些对加速常用虚拟指令的支持,使得嵌套VM成为可能.

我将尝试分析实现嵌套虚拟化所面临的问题.
我不是在处理整个事情 - 我正在考虑基本情况,只是忽略了处理硬件虚拟化的所有部分; 本身与软件虚拟化一样有问题的部分.

注意
我不是虚拟化技术专家,根本没有经验 - 欢迎更正.
这个答案的目的是让读者在概念上相信嵌套虚拟化是可能的,并概述要面对的问题.

VT-X

逻辑处理器通过执行进入VMX操作vmxon- 一旦进入模式,处理器就处于根模式.
根模式是VMM的模式,它可以启动,恢复和处理VM.

然后,VMM将当前VMCS(VM控制结构)设置为vmptrld- VMCS包含虚拟化guest虚拟机所需的所有元数据.
该VMCS被读取和写入不直接存储器访问vmreadvmwrite说明.

最后,VMM执行vmlaunch以开始执行guest 虚拟机.

接受虚拟机

现在,逻辑处理器正在虚拟化环境中执行.
假设guest虚拟机本身就是VMM,我们称之为非root VMM - 它需要重复上述步骤.

但英特尔在其手册中很清楚(手册3 - 第25.1.2章):

以下指令使VM退出,当他们在VMX非根操作被执行:
[...]
这也是与VMX引入的指令,其包括真:
[...], VMLAUNCH,VMPTRLD,[...]和VMXON

vmxon该指令导致VM退出,根VMM从最后一条指令恢复vmlaunch,可以检查VMCS是否退出,并采取适当的措施.
我不是一个经验丰富的VMM编写器所以我不确定根VMM必须做什么才能模拟这个指令 - 因为vmxon在VMX根模式下执行将失败并执行一个vmxoff后面跟一个vmxonVM给出的VM Region root VMM似乎是一个安全漏洞(或导致它)我相信所有root VMM必须做的是记录guest虚拟机现在处于"VMX root模式".
这里需要引号:此模式仅存在于软件中,当根VMM将控制权交还给非根VMM时,CPU将处于非root VMX模式.

之后,非根VMM将尝试vmptrld用于设置当前VMCS.
vmptrld将导致VM退出并且根VMM再次受到控制 - 如果CPU不支持VMCS阴影,则根VMM必须记录非根VMM给出的指针现在是当前VMCS - 如果CPU执行支撑VMCS遮蔽的VMM设置VMCS链接指针的字段 VMCS由非根VMM给予VMCS(用于虚拟化的非根VMM的一个).
VMM以这种或那种方式知道哪个虚拟化VMCS是活动的.

vmread并且vmwrite由非root VMM执行将会或不会导致VM退出.
如果VMCS阴影处于活动状态,则CPU将不执行VM Exit,而是读取活动VMCS(称为影子VMCS)中的VMCS链接指针所指向VMCS.
这将加速嵌套VM的虚拟化.
如果VMCS阴影未激活,则CPU将退出VM,并且根VMM必须模拟读/写.

最后,非root VMM将启动其VM - 这是一个嵌套的VM.
vmlaunch将触发VM退出.
根VMM必须做一些事情:

  • 将VMCS保存在某处.
  • 合并当前VMCS和非根VMM VMCS - 由于VMCS控制,例如,哪些事件导致VM退出,合并的VMD必须是这两者的联合.
  • 将合并的VMCS加载为CPU的当前VMCS
  • 做一个vmlaunch/ vmresume.

梦想里面

现在CPU正在执行嵌套VM(VVM - 虚拟VM?).
当敏感指令或事件导致VM退出时会发生什么?

从处理器的角度来看,只有两个级别的虚拟化:根VMX模式和非根VMX模式.
由于guest虚拟机处于非root VMX模式,因此控制权将转移回根VMX模式代码 - 即根VMM.

根VMM现在必须了解该事件是来自其VM还是来自其VM的VM.
这可以通过跟踪vmlaunch/ vmresume和检查VMCS中的位来完成.

如果VM Exit被定向到非root VMM,则根VMM必须加载其原始VMCS,最终在其中设置非root VMM的链接,更新非root VMM VMCS状态位并执行a vmresume.
如果VM Exit指向它,则根VMM将像任何其他VM Exit一样处理它.

梦中的梦想

如果我们想在嵌套VM中创建VM,该怎么办?一种虚拟虚拟VM(VVVM).

有两件事需要注意:

  1. 根VMM仍然是在每个VM Exit期间调用的VMM.
    即使VVVM深度为三级,也不是非根非根VMM是第一个和/或唯一用于虚拟化它的管理器.
    从安全角度来看,根VMM是弱链接.
  2. 硬件并不真正支持任意深度嵌套.
    VMM可能不需要太多努力就可以从支持1级嵌套到n级嵌套(我再次在这里没有经验丰富),但仍然需要如上所述的特殊支持.
    它并不像启动VM那么容易,CPU会处理其他所有事情.

AMD-V

在AMD-v中没有root和非root模式,CPU开始执行一个VM vmrun,它指向一个指向VMCB(VM控制块)的指针,该指针与Intel的VMCS具有相同的用途.
vmrunCPU处于访客模式时.

VMCB已缓存,但只能通过常规内存访问来读取.
vmload/ vmsave指令明确装入和缓存中的VMCB字段受缓存保存.

这个界面比英特尔的界面更容易,但它同样强大 - 即使在嵌套虚拟化方面也是如此.

假设我们在VM中并且代码执行vmrun- 因此我们正在虚拟化VMM.

从技术上讲,VMM可以选择何时vmrun触发或不触发VM退出.
然而,实际上,AMD-v目前要求前者始终如此:

以下条件被视为非法状态组合:[...]
*VMRUN截取位清除

因此,根VMM(我将使用与英特尔情况相同的术语)将获得控制并且必须模拟vmrun (因为硬件仅支持单级虚拟化).

根VMM可以将当前VMCB与非根VMM VMCB保存并合并,并继续执行与vmrun英特尔情况相同的操作.

在退出时,根VMM必须确定退出是指向它还是指向非根VMM,再次这可以跟踪vmrunVMCB中的控制位和控制位.

再次做梦

我们在VM中建立了一个相对简单的虚拟机 - 现在虚拟机出口会发生什么?
根VMM接收退出,如果定向到非根VMM,则必须恢复其原始VMCB并恢复运行(即使用vmrun其原始VMCB).

AMD-v 通过考虑其地址访客地址来支持vmsavevmload指令的快速虚拟化,因此受制于通常的页面嵌套虚拟化.

再次启动Inception

与英特尔的情况一样,只要VMM支持该功能,就可以再次嵌套虚拟化.

针对英特尔案例的重要安全警告也适用于AMD的案例.


由于其实现定义的格式以及内存区域可以用作未实时更新的溢出区域这一事实

  • 来自英特尔虚拟化技术专家和嵌套虚拟化专家,这个答案非常出色; 不需要更正. (2认同)