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

时间:2017-03-04 15:33:00

标签: assembly x86 virtual-machine cpu virtualization

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

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

如果有可能支持仿真/拦截VMX呼叫的VMM实施(VMware,Parallels,KVM,...)?

2 个答案:

答案 0 :(得分:10)

英特尔的 VT-x 和AMD的 AMD-V 也不支持硬件中的完全递归虚拟化 - 其中CPU保留了嵌套虚拟化环境的层次结构,与call / ret对相同。

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

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

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

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

VT-X

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

然后,VMM将当前VMCS(VM控制结构)设置为vmptrld - VMCS包含虚拟化访客所需的所有元数据。
VMCS的读取和写入不是通过直接存储器访问,而是使用vmreadvmwrite指令。

最后,VMM执行vmlaunch以开始执行访客。

接受虚拟机

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

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

  

以下说明在VMX非root操作中执行时会导致 VM退出
  [...]
   VMX引入的说明也是如此,其中包括:
  [...],VMLAUNCHVMPTRLD,[...]和VMXON

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

之后,非root VMM将尝试使用vmxon来设置当前的VMCS vmptrld将导致VM退出并且根VMM再次处于控制状态 - 如果CPU不支持 VMCS shadowing 根VMM必须记录指针由非根VMM给出的是现在的VMCS - 如果CPU确实支持 VMCS阴影,则VMM设置 VMCS链接指针字段> VMCS(用于虚拟化非root VMM的VMCS)到非root VMM给出的VMCS。
VMM知道哪种虚拟化VMCS处于活动状态。

由非root VMM执行的

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

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

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

梦想中

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

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

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

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

梦中梦想中的梦想

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

有两件事需要注意:

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

    在AMD-v中没有root和非root模式,CPU开始执行一个vmresume的VM,它指向一个指向VMCB(VM控制块)的指针,该指针用于与Intel相同的目的&# 39; s VMCS。
    vmresume CPU处于访客模式时。

    VMCB已缓存,但只能通过常规内存访问来读取 vmrun / vmrun指令显式加载到缓存中并从缓存中保存需要缓存的VMCB字段。

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

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

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

      

    以下条件被视为非法状态组合:   [...]
      * vmrun拦截位清晰

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

    根VMM可以将当前VMCB与非root VMM VMCB保存并合并,并按照英特尔情况继续VMRUN

    退出时,root-VMM必须确定退出是指向它还是指向非根VMM,再次可以跟踪vmrun和VMCB中的控制位。

    再次做梦

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

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

    重新启动

    与英特尔案例一样,只要VMM支持该功能,虚拟化就可以再次嵌套。

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

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

答案 1 :(得分:0)

在阅读了更多有关虚拟化的内容后,我偶然发现虚拟机上的这个ticket

这是针对此功能的功能请求,并且通过评论阅读VMware Workstation已经实现了它,因此它确实必须正常工作。